In C++, if I want to have a member of a class that has no default constructor, I need to explicitly initialize it like this:
class a
{
a(int)
{
}
};
class b
{
a x;
b() : x(3)
{
}
};
However, sometimes the initialization for, say, x, could not be so simple. It could either be a very very complicated formula or a whole, algorithmic function with fors and ifs that needs to be computed. I usually solve it like this:
class b
{
a * x;
b()
{
// Do some very complicated computations
this->x = new a(result_of_complicated_computations);
}
};
Which, however, forces me to delete the pointer at the moment of destruction, it slightly less performing and makes my code somehow untidy and ugly. I am really surprised that there is no way to compute parameters for constructors of members within the constructor of the class, without having to use this kind of tricks.
Are there more elegant solutions to this?
Use a helper function:
class b
{
a x;
b() : x(complicated_computation()) { }
private:
static int complicated_computation() {
return result_of_complicated_computations;
}
};
And the default-constructor isn't deleted, but undeclared.
Do the computations in a function:
static a complicated_computations();
b() : x(complicated_computations()) {}
I don't get it. If you have:
class A
{
private:
//a lot of members
public:
A(/* complex object used for construction */)
: //initialize members
{ }
}
You can simply do:
class B
{
private:
A a;
public:
B()
: a(call_to_function_that_generates_this_complex_data())
{ }
};
You can even use your member functions during construction. But note, that:
ยง 12.6.2.13:
Member functions (including virtual member functions,
10.3) can be called for an object under construction.(...) However, if these operations are performed in a ctor-initializer (or in a function
called directly or indirectly from a ctor-initializer) before all the
mem-initializers for base classes have completed, the result of the
operation is undefined.
Related
Consider I want to wrap some library code inside an object. That library needs to be set up and initialized by calling some function inside the constructor of that wrapper class.
The librarie's "objects" then diverge into creating more, different "objects" that the wrapper class wraps in form of yet another wrapper object that should be a plain member of that class.
But as far as I see it, members of classes can only be initialized or created by calling their constructor in the initalizer list of the constructor. The execution of these bits of code preceed the constructor of the actual class that does the initialization of the library and its environment, making it impossible for me to actually initialize that member object as a member and instead force me to initialize it as a pointer to the 2nd wrapper, because its constructor must be called manually within the first constructor's code.
Example:
class A {
public:
A() {
if(!wrapped_library_init()) {
exit(CRITICAL_ERROR);
}
ptr_to_some_library_metadata *a = library_function(); /*Needs to
be called after wrapped_library_init() or needs a pointer to some
wrapped object created inside this constructor */
//initialize b
}
private:
B b; //Wants to be a member but can not
};
class B {
B(ptr_to_some_library_metadata *a);
}
Member objects can only be constructed in the member initializer list. There are a few techniques which can be used to make it possible to initialize an object, though:
Use a helper [lambda] function doing the necessary extra work before return a suitable object. For example:
A()
: B([]{
if (!wrapped_library_init()) {
exit(CRITICAL_ERROR);
}
return library_function();
}()) {
}
You can delay construction by using a union with just the appropriate member. When using this technique the member needs to be explicitly destructed, for example:
class A {
union Bu { B b };
Bu b;
public:
A() {
if (!wrapped_library_init()) {
exit(CRITICAL_ERROR);
}
new(&b.b) B(library_function());
}
~A() {
b.b.~B();
}
// ...
};
I'd personally use the first approach. However, there are cases when using a union to delay construction is helpful.
Initializer lists are there to use another constructor than the default constructor.
But nothing impedes you for creating a custom function that will initialize b:
class A {
public:
A():b(init()) {
}
private:
B b; //Wants to be a member but can not
static B init()
{
if(!wrapped_library_init()) {
exit(CRITICAL_ERROR);
}
ptr_to_some_library_metadata *a = library_function(); /*Needs to
be called after wrapped_library_init() or needs a pointer to some
wrapped object created inside this constructor */
return B(a);
}
};
Wrap your library inside a class:
class LibraryWrapper
{
public:
LibraryWrapper()
{
if(!wrapped_library_init()) {
exit(CRITICAL_ERROR);
}
lib_data.reset(library_function()); /*Needs to
be called after wrapped_library_init() or needs a pointer to some
wrapped object created inside this constructor */
}
//~LibraryWrapper() {/**/}
//LibraryWrapper(const LibraryWrapper&) {/**/} // =delete; ?
//LibraryWrapper& operator=(const LibraryWrapper&) {/**/} // =delete; ?
//private: // and appropriate interface to hide internal
std::unique_ptr<ptr_to_some_library_metadata, CustomDeleter> lib_data;
};
class B {
public:
explicit B(ptr_to_some_library_metadata *a);
// ...
};
And use extra member or inheritance:
class A
{
public:
A() : b(lib.lib_data.get()) {}
private:
LibraryWrapper lib; // placed before B
B b;
};
I'm inheriting a class and I would like to call one of its constructors. However, I have to process some stuff (that doesn't require anything of the base class) before calling it. Is there any way I can just call it later instead of calling it on the initializer list? I believe this can be done in Java and C# but I'm not sure about C++.
The data that I need to pass on the constructor can't be reassigned later, so I can't just call a default constructor and initialize it later.
Is there any way I can just call it later instead of calling it on the initializer list?
No, you cannot. The base class constructor must be called in the initializer list, and it must be called first.
In fact, if you omit it there, the compiler will just add the call implicitly.
I believe this can be done in Java and C# but I'm not sure about C++.
Neither C# nor Java allow this either.
What you can do, however, is call a method as an argument of the base class constructor call. This is then processed before the constructor:
class Derived {
public:
Derived() : Base(some_function()) { }
private:
static int some_function() { return 42; }
};
As was said by several people answering, you cannot delay the invocation of a base class constructor, but Konrad has given a good answer that might well solve your problem. However, this does have its drawbacks (for example, when you need to initialize several functions with values whose calculations share intermediate results), so just to be complete, here's another way of solving the problem of fixed initialization order, by using it.
Given the fixed order of initialization, if you have control over the derived class (and how else would you come to fiddle with one of its ctors?), you can sneak in a private base so that it is going to be initialized before the other base, which can then be initialized with the private base's already calculated values:
class my_dirty_little_secret {
// friend class the_class;
public:
my_dirty_little_secret(const std::string& str)
{
// however that calculates x, y, and z from str I wouldn't know
}
int x;
std::string y;
float z;
};
class the_class : private my_dirty_little_secret // must be first, see ctor
, public the_other_base_class {
public:
the_class(const std::string str)
: my_dirty_little_secret(str)
, the_other_base_class(x, y, z)
{
}
// ...
};
The my_dirty_little_secret class is a private base so that users of the_class cannot use it, all of its stuff is private, too, with explicit friendship granting only the_class access to it. However, since it's listed first in the base class list, it will reliably be constructed before the_other_base_class, so whatever it calculates can be used to initialize that.
A nice comment at the base class list hopefully prevents from others breaking things by refactoring.
IMHO I dont think it is possible to defer calling the base class constructor in the way that you mentioned.
Wow, we were all young once. This answer won't work, so don't use it. Content left for historical purposes.
If you have full control over the base class, I'd recommend adding a protected method to do the class initialization, make it virtual, and put the your derived class implementation details in it before it calls its base:
class Base
{
public:
Base()
{
Initialize();
}
protected:
virtual void Initialize()
{
//do initialization;
}
};
class Derived : Base
{
public:
Derived() : Base()
{
}
protected:
virtual void Initialize()
{
//Do my initialization
//call base
Base::Initialize();
}
};
Another option, based on the suggestion from #Konrad is to have a static method to construct the object, e.g.:
class Derived {
public:
Derived(int p1, int p2, int p3) : Base(p1, p2) { }
static Derived* CreateDerived(int p3) { return new Derived(42, 314, p3); }
};
Ive found this useful when extending a class from a library and having multiple parameters to override.
You can even make the constructor private
struct base{
base(int x){}
};
struct derived : base{
derived(int x) : base(x){}
};
This is how base class constructors are invoked in C++ from the initialization list of derived class.
Let's say that I have two classes A and B.
class A
{
private:
int value;
public:
A(int v)
{
value = v;
}
};
class B
{
private:
A value;
public:
B()
{
// Here's my problem
}
}
I guess it's something basic but I don't know how to call A's constructor.
Also the compiler demands a default constructor for class A. But if A has a default constructor than wouldn't the default constructor be called whenever I declare a variable of type A. Can I still call a constructor after the default constructor has been called? Or can I declare an instance of a class and then call a constructor later?
I think this could be solved using pointers but can that be avoided ?
I know that you can do something like this in C#.
EDIT: I want to do some computations in the constructor and than initialize the classes. I don't know the values beforehand.
Let's say I'm reading the value from a file and then I initialize A accordingly.
The term you are looking for is initializer list. It is separated from the constructor body with a colon and determines how the members are initialized. Always prefer initialization to assignment when possible.
class A
{
int value;
public:
A(int value) : value(value) {}
};
class B
{
A a;
public:
B(int value) : a(value) {}
}
I want to do some computations in the constructor and than initialize the classes. I don't know the values beforehand.
Simply perform the computation in a separate function which you then call in the initializer list.
class B
{
A a;
static int some_computation()
{
return 42;
}
public:
B() : a(some_computation()) {}
}
You use an initialization list to initialize the member variables.
public:
B() : value(4) { // calls A::A(4) for value.
}
Or can I declare an instance of a class and then call a constructor later?
Yes, you can do that. Instead of (A value;) declare (A* value;), and then B's constructor will be B():value(new A(5)){}.
In the B's destructor you will have to do delete value;
I think this could be solved using pointers but can that be avoided ?
Yes. Use shared_ptr.
Try:
B() :
value(0)
{
// Here's my problem
}
I've trying to achieve something like this:
class Base
{
public:
Base(string S)
{
...
};
}
class Derived: Base
{
public:
int foo;
string bar()
{
return stringof(foo); // actually, something more complex
};
Derived(int f) : foo(f), Base(bar())
{
};
}
Now, this doesn't work as I want, because bar() is called in the Derived constructor before foo is initialized.
I considered adding a static function similar to bar() which takes foo as a parameter - and using that in the initialization list, but thought I'd ask if there were any other techniques that could be used to dig myself out of this one...
Edit: Thanks for feedback - here's how I was going to handle the static function. Not sure if the overload between a static and non-static function is too clever, but...
class Derived: Base
{
public:
int foo;
static string bar(int f)
{
return stringof(f); // actually, something more complex
}
string bar()
{
return bar(foo);
};
Derived(int f) : Base(bar(f)) , foo(f)
{
};
}
Yes, using a function (static class method or regular function) that takes foo as a parameter and returns a string is a good solution. You can call this same function from Derived::bar to prevent code duplication. So, your constructor would look like this:
Derived(int f) : Base(stringof(f)), foo(f) {}
I place the call to the Base constructor first in the list to emphasize the order in which the initializations occur. The ordering of the initializer list has no effect as all class members are initialized in the order that they are declared in the class body.
This is a very clean, functional approach to the problem. However, if you still would like to weigh alternatives then consider using composition instead of inheritance for the relationship between the Derived and Base classes:
class Base {
public:
Base(string S) { ... }
void bat() { ... }
};
class Derived {
Base *base;
int foo;
public:
Derived(int f) : base(NULL), foo(f) {
base = new Base(bar());
}
~Derived() {
delete base;
}
string bar() {
return stringof(foo); // actually, something more complex
}
void bat() {
base->bat();
}
};
You will need to consider the pros and cons for your specific situation. With Derived holding a reference to Base you gain greater control over the initialization order.
You can only call static functions in the initializer list. The way you have it in your code:
class Derived: Base
{
public:
int foo;
string bar()
{
return stringof(foo); // actually, something more complex
};
Derived(int f) : foo(f), Base(bar())
{
};
}
Will still initialize Base first, and then foo. The order of how you write things in an constructor initializer list does not matter in any way. It will always construct in this order:
First, all virtual base classes
Then the non-virtual base classes in the order they appear in the base-classes list
Then all member objects in the order they are defined in the class definition.
Thus, you end up calling stringof with an uninitialized value. This problem is solved in boost::base_from_member. Also note that calling any nonstatic member function before all the constructor initializers of all base-classes completed is undefined behavior.
Calling static functions, however, is totally fine:
class Derived: Base
{
public:
int foo;
static string bar(int f)
{
return stringof(f); // actually, something more complex
};
Derived(int f) : Base(bar(f)), foo(f)
{
};
}
The base class constructor always gets called before initializing the other members of the derived class; your compiler should be giving you a warning for having the initializers in the wrong order. The only correct solution is to make bar() a static method that takes f as a parameter.
The constructor is for, well, constructing the object. This means that, until it returns, there isn't an object there, and therefore that calling member functions just isn't going to work reliably. As everybody else says, use a static function or a non-member function.
I've been wanting to do this as well, but I gave up in the end.
Any suitable function call could be used as the parameter of Base().
Another option is to add and alternative constructor to Base that takes an int and does the conversion to 'string' itself.
Just move your constructor code to an Initialize() function and call it from the constructor. This is much simpler than static/nonstatic overriding or anything like that.
For many classes C1, C2, and so forth, the initialization looks equal, and it's just a little something differs from class to class. Hence I created a base class B that hosts the initalizations, e.g.:
class B {
public:
B()
{
// complex initializations
int a = doSomething();
// more complex stuff with `a`
};
virtual int doSomething()
{return 2 * doSomethingHelper();}
protected:
virtual int doSomethingHelper() = 0;
};
class C: public B {
protected:
virtual int doSomethingHelper()
{return 1;}
};
int main() {
C c;
return 0;
}
This code fails with
pure virtual method called
terminate called without an active exception
Aborted (core dumped)
since doSomethingHelper() is used to initialize B.
I'm wondering if there is a better design. My objectives are:
Make C's user interface as easy as possible: C has no constructor arguments.
Make C itself as minimalistic as possible such that other concretizations of B are short. Ideally, it only contains the doSomethingHelper.
A suggestion for a more sane design would be appreciated.
Short answer:
Don't call virtual functions from within a constructor. Doing so will get you in trouble.
Longer answer:
The declaration C c creates and constructs, in steps, an instance of class C. That object is first constructed as a class A object, then as a class B object, and finally as a class C object. At the point that B::B() is called, there is no notion that the object will eventually be an instance of class C.
When B::B() is invoked, it calls the virtual function doSomething(), which in this case means calling B::doSomething(). There's no problem yet; that function exists. The problem is with the call to doSomethingHelper() within the body of B::doSomething(). That function is pure virtual at this point. As noted above, there is no indication that this object will eventually be an instance of class C. The function C::doSomethingHelper() cannot be called cannot be called from B::B() or A::A(). There is no A::doSomethingHelper(), no B::doSomethingHelper(), so the function doesn't exist. You're toast.
I'm wondering if there is a better design.
There are lots of better designs. The simplest is to not call doSomething() from within the constructor of class B. Move that call to the constructor of class C. Even then, calling a virtual function from within the constructor may not be a good idea. What if class D inherits from class C and overrides C::doSomethingHelper()? An instance of class D will be constructed by calling C::doSomethingHelper() rather than D::doSomethingHelper().
According to the standard:
10.4/6: Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making a virtual call
(10.3) to a pure virtual function directly or indirectly for the
object being created (or destroyed) from such a constructor (or
destructor) is undefined
This is because, when you construct C:
first the subobject B is constructed using the B() constructor. At that time, it's still B's virtual functions which are used. You get the error because at this moment, doSomethingHelper() is not defined for it.
Only once B() is completed will the virtual will C's virtual functions become active.
Two phased initialisation
This situation can only be avoided through a two phased initialisation: first construction, then calling an initialisation function. Not so nice and user friendly as you'd have desired.
class B {
public:
B() { /* complex initializations */ }
...
protected:
void init() { // the rest of the what you wanted in constructor
int a = doSomething();
// more complex stuff with `a`
}
};
The two phased initialisation could then be triggered via C's constructor:
class C {
public:
C() : B() { // first B is constructed
init(); // then the body of C's constructor is executed
}
...
};
Variant for the two-phased initialisation
There's a small variant that you can use, to hide the two phase approach, and let more freedom for the user about defining or not their own constructor.
In B you define an auxiliary nested class:
protected:
class initialiser {
public:
initialiser(B*b) {b->init();} // the constructor launches the second phase init
};
In C , you just need to add a protected member variable:
class C: public B {
...
protected:
B::initialiser bi{this}; // this triggers automaticcaly the second phase
...
};
The standard's rules ensure that first B is constructed and then the members of C. Demo here.
You can't use dynamic dispatching to a derived class in a constructor.
When B's constructor is running, the C subobject has not yet been created, so none of its overriden functions can be used. As B doesn't provide an implementation for doSomethingHelper, nothing sensible can be done.
Move all the complexity into B::doSomething, and call that method from the end of inheritance chain, C:
class B {
public:
B()
{};
virtual int doSomething()
{
// complex initializations
int a = 2 * doSomethingHelper();
// more complex stuff with `a`
return a;
}
protected:
virtual int doSomethingHelper() = 0;
};
class C: public B {
public:
C(): B()
{
int a = doSomething();
}
protected:
virtual int doSomethingHelper()
{return 1;}
};
int main() {
C c;
return 0;
}
This might require you to make some of B formerly private members protected such that they can be initialized by C.