Observation: The constructor of ClassMain needs to call Init before it can constructor a member variable a. Since the ClassA has no default constructor, the code doesn't compile.
ClassA
{
public:
// This class has no default constructor
ClassA(...){}
};
class ClassMain
{
public:
ClassMain(...) {
Init(...);
a = ClassA(...); // error: ClassA has no default constructor
// a has to been constructed after the Init is called!
}
ClassMain(...) {
Init(...);
call other functions
a = ClassA(...);
}
private:
// initialize environment
void Init(...) {}
private:
ClassA a;
};
Question> The simple solution is to provide a default constructor for ClassA. However, I would like to know whether there is a better solution to address the issue above?
The better solution is not to require an Init function at all. You're trying to reinvent constructors, and breaking their design in the process.
If Init does too much work for a constructor, then do it outside and pass the resulting resources into ClassMain as a constructor argument; notice how you're already doing all the work in the constructor's scope anyway, thereby not gaining anything appreciable over proper initialisation.
Of course, if you must perform a ton of work before initialising a, and you cannot pass in a ClassA& from the outside and initialise from that, then you're simply going to have to have a be an indirect member.
There is one nasty workaround you could use: have Init actually be a base constructor...
The obvious solution is to call Init() from the initializer list of an early member or a base class. Once this subobject is constructed its results can be passed to the constructors of other subobjects. For example, when defining stream classes I typically privately inherit from a virtual base containing the stream buffer:
struct somebuf_base {
somebuf sbuf;
// ...
};
class somestream
: private virtual somebuf_base
, public std::ostream
{
public:
somestream(someargs)
: somebuf_base(someargs)
, std::ostream(&this->sbuf) {
}
// ...
};
Since base classes are constructed in the order they appear but virtual bases before non-virtual bases, the base class containing the sbuf member is constructed first. Its constructor replaces your Init() function.
When using C++ as of the 2011 revision, you might also use forwarding constructors to share logic between multiple constructors.
It's easier to take a pointer to ClassA; So, you can instantiate it whenever you want.(after the init())
If you used a pointer, don't forget to implement the virtual destructor and release the allocated memory for the ClassA *a
If you absolutely must call some function at the start of your constructor, and can't put that setup into some base class or early-constructed member, you could use this ugly trick:
ClassMain::ClassMain(int main_param)
: a( (Init(init_arg), class_a_arg1), class_a_arg2 )
{
}
In this case: No, we cannot avoid that.
The reason is that when calling Init or any other member function you are guaranteed by the language that the object you are in exists. As a is a member of ClassMain it must be constructed before any function in ClassMain can be called.
The only chance that you have here is to refactor the code.
Related
I know we can explicitly call the constructor of a class in C++ using scope resolution operator, i.e. className::className(). I was wondering where exactly would I need to make such a call.
You also sometimes explicitly use a constructor to build a temporary. For example, if you have some class with a constructor:
class Foo
{
Foo(char* c, int i);
};
and a function
void Bar(Foo foo);
but you don't have a Foo around, you could do
Bar(Foo("hello", 5));
This is like a cast. Indeed, if you have a constructor that takes only one parameter, the C++ compiler will use that constructor to perform implicit casts.
It is not legal to call a constructor on an already-existing object. That is, you cannot do
Foo foo;
foo.Foo(); // compile error!
no matter what you do. But you can invoke a constructor without allocating memory - that's what placement new is for.
char buffer[sizeof(Foo)]; // a bit of memory
Foo* foo = new(buffer) Foo(); // construct a Foo inside buffer
You give new some memory, and it constructs the object in that spot instead of allocating new memory. This usage is considered evil, and is rare in most types of code, but common in embedded and data structure code.
For example, std::vector::push_back uses this technique to invoke the copy constructor. That way, it only needs to do one copy, instead of creating an empty object and using the assignment operator.
Most often, in a child class constructor that require some parameters :
class BaseClass
{
public:
BaseClass( const std::string& name ) : m_name( name ) { }
const std::string& getName() const { return m_name; }
private:
const std::string m_name;
//...
};
class DerivedClass : public BaseClass
{
public:
DerivedClass( const std::string& name ) : BaseClass( name ) { }
// ...
};
class TestClass :
{
public:
TestClass( int testValue ); //...
};
class UniqueTestClass
: public BaseClass
, public TestClass
{
public:
UniqueTestClass()
: BaseClass( "UniqueTest" )
, TestClass( 42 )
{ }
// ...
};
... for example.
Other than that, I don't see the utility. I only did call the constructor in other code when I was too young to know what I was really doing...
I think the error message for compiler error C2585 gives the best reason why you would need to actually use the scope-resolution operator on the constructor, and it does in with Charlie's answer:
Converting from a class or structure type based on multiple inheritance. If the type inherits the same base class more than once, the conversion function or operator must use scope resolution (::) to specify which of the inherited classes to use in the conversion.
So imagine you have BaseClass, and BaseClassA and BaseClassB both inherit BaseClass, and then DerivedClass inherits both BaseClassA and BaseClassB.
If you are doing a conversion or operator overload to convert DerivedClass to a BaseClassA or BaseClassB, you will need to identify which constructor (I'm thinking something like a copy constructor, IIRC) to use in the conversion.
In general you do not call the constructor directly. The new operator calls it for you or a subclass calls the parent class' constructors. In C++, the base class is guarenteed to be fully constructed before the derived class' constructor starts.
The only time you would call a constructor directly is in the extremely rare case where you are managing memory without using new. And even then, you shouldn't do it. Instead you should use the placement form of operator new.
I don't think you would typically use that for the constructor, at least not in the way you're describing. You would, however, need it if you have two classes in different namespaces. For example, to specify the difference between these two made-up classes, Xml::Element and Chemistry::Element.
Usually, the name of the class is used with the scope resolution operator to call a function on an inherited class's parent. So, if you have a class Dog that inherits from Animal, and both of those classes define the function Eat() differently, there might be a case when you want to use the Animal version of eat on a Dog object called "someDog". My C++ syntax is a little rusty, but I think in that case you would say someDog.Animal::Eat().
There are valid use cases where you want to expose a classes constructors. If you wish to do your own memory management with an arena allocator for example, you'll need a two phase construction consisting of allocation and object initialization.
The approach I take is similar to that of many other languages. I simply put my construction code in well known public methods (Construct(), init(), something like that) and call them directly when needed.
You can create overloads of these methods that match your constructors; your regular constructors just call into them. Put big comments in the code to warn others that you are doing this so they don't add important construction code in the wrong place.
Remember that there is only one destructor method no matter which construction overload was used, so make your destructors robust to uninitialized members.
I recommend against trying to write initializers that can re-initialize. It's hard to tell the case where you are looking at an object that just has garbage in it because of uninitialized memory vs. actually holding real data.
The most difficult issue comes with classes that have virtual methods. In this case the compiler normally plugs in the vtable function table pointer as a hidden field at the start of the class. You can manually initialize this pointer, but you are basically depending on compiler specific behavior and it's likely to get your colleagues looking at you funny.
Placement new is broken in many respects; in the construction/destruction of arrays is one case so I tend not to use it.
Consider the following program.
template<class T>
double GetAverage(T tArray[], int nElements)
{
T tSum = T(); // tSum = 0
for (int nIndex = 0; nIndex < nElements; ++nIndex)
{
tSum += tArray[nIndex];
}
// Whatever type of T is, convert to double
return double(tSum) / nElements;
}
This will call a default constructor explicitly to initialize the variable.
class Base {
public:
Base(int a) : a_(a) {
//do something
someMethod();
//do something else
};
protected:
int a_;
virtual void someMethod() = 0 {};
};
class Derived : Base {
public:
Derived() {
Base::Base(42);
}
protected:
void someMethod() override {
//realisation
}
};
int main() {
Derived *obj = new Derived();
delete obj;
}
This code doesn't work by two mistakes: base class's default constructor is needed and base class's constructor with parameters can't be called because of using abstract methods
My problem is that someMethod() realised in class Derived is not called at all when I create object of class Derived. Also I don't want to use default constructor of class Base, but compiler is swearing.
How can I correct my code to see functionality that I want?
How can I correct my code to see functionality that I want?
Remove the call to a pure virtual function in the constructor of Base.
Call someMethod in the constructor of the derived class that overrides it instead.
Provide an initialiser to the Base subobject in the member initiliser list. If you don't provide an initialiser to the base, it will be default initialised.
Why this cannot work ?
This design will not work because of the way obects are constructed.
When you construct a Derived, the first thing happening is that a Base object is constructed with a Base constructor. There is no Derived object at this moment, so if you'd invoke the virtual function in the Base constructor, it would be the virtual that would be valid for the Base class until you leave the Base constructor's body.
This is allowed by the standard, but with restrictions:
[base.class.init]/16: Member functions (including virtual member functions) 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 program
has undefined behavior.
These restriction do not apply to virtual functions that are called from the constructor body, since the body is executed after all initializers.
But in your case the virtual function is pure virtual for the Base. So it's UB according to the following clause:
[class.abstract]/6: Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making
a virtual call to a pure virtual function directly or
indirectly for the object being created (or destroyed) from such a
constructor (or destructor) is undefined.
What is the alternative
There is unfortunately no other real alternative than using a two step initialization in which you first construct the object and then call an initialization function before using the object.
The only issue with this approach is the risk of forgetting the call to the initialization function. You can protect you against this:
using a flag to indicate if the intialization has taken place and check this flag in all member functions (yes, it's a little overhead).
if you have an abstract class, you may perhaps use a factory pattern (factory method or abstract factory). You could then let the factory do the call.
you may use the builder pattern, and make sure that the constructor is only visible to the builder who won't forget the initialization either.
Other problems with your code
You must be careful about how you "call" the base constructor from the derived constructor:
class Derived : Base {
public:
Derived() : Base(42) // this is the correct place !
{
//Base::Base(42); //<==== OUCH !!! NO !! This creates a temporary base object !!
}
...
};
You'd also need to be careful about the pure virtuals (I don't know if it's a typo or if your compiler could compile your code):
virtual void someMethod() = 0; // if it's abstract, no pending {} !
I know that calling a virtual method from a base class constructor can be dangerous since the child class might not be in a valid state. (at least in C#)
My question is what if the virtual method is the one who initializes the state of the object ? Is it good practice or should it be a two step process, first to create the object and then to load the state ?
First option: (using the constructor to initialize the state)
public class BaseObject {
public BaseObject(XElement definition) {
this.LoadState(definition);
}
protected abstract LoadState(XElement definition);
}
Second option: (using a two step process)
public class BaseObject {
public void LoadState(XElement definition) {
this.LoadStateCore(definition);
}
protected abstract LoadStateCore(XElement definition);
}
In the first method the consumer of the code can create and initialize the object with one statement:
// The base class will call the virtual method to load the state.
ChildObject o = new ChildObject(definition)
In the second method the consumer will have to create the object and then load the state:
ChildObject o = new ChildObject();
o.LoadState(definition);
(This answer applies to C# and Java. I believe C++ works differently on this matter.)
Calling a virtual method in a constructor is indeed dangerous, but sometimes it can end up with the cleanest code.
I would try to avoid it where possible, but without bending the design hugely. (For instance, the "initialize later" option prohibits immutability.) If you do use a virtual method in the constructor, document it very strongly. So long as everyone involved is aware of what it's doing, it shouldn't cause too many problems. I would try to limit the visibility though, as you've done in your first example.
EDIT: One thing which is important here is that there's a difference between C# and Java in order of initialization. If you have a class such as:
public class Child : Parent
{
private int foo = 10;
protected override void ShowFoo()
{
Console.WriteLine(foo);
}
}
where the Parent constructor calls ShowFoo, in C# it will display 10. The equivalent program in Java would display 0.
In C++, calling a virtual method in a base class constructor will simply call the method as if the derived class doesn't exist yet (because it doesn't). So that means that the call is resolved at compile time to whatever method it should call in the base class (or classes it derived from).
Tested with GCC, it allows you to call a pure virtual function from a constructor, but it gives a warning, and results in a link time error. It appears that this behavior is undefined by the standard:
"Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making a virtual call (class.virtual) to a pure virtual function directly or indirectly for the object being created (or destroyed) from such a constructor (or destructor) is undefined."
With C++ the virtual methods are routed through the vtable for the class that is being constructed. So in your example it would generate a pure virtual method exception since whilst BaseObject is being constructed there simply is no LoadStateCore method to invoke.
If the function is not abstract, but simply does nothing then you will often get the programmer scratching their head for a while trying to remember why it is that the function doesn't actually get called.
For this reason you simply can't do it this way in C++ ...
For C++ the base constructor is called before the derived constructor, which means that the virtual table (which holds the addresses of the derived class's overridden virtual functions) does not yet exist. For this reason, it is considered a VERY dangerous thing to do (especially if the functions are pure virtual in the base class...this will cause a pure-virtual exception).
There are two ways around this:
Do a two-step process of construction + initialization
Move the virtual functions to an internal class that you can more closely control (can make use of the above approach, see example for details)
An example of (1) is:
class base
{
public:
base()
{
// only initialize base's members
}
virtual ~base()
{
// only release base's members
}
virtual bool initialize(/* whatever goes here */) = 0;
};
class derived : public base
{
public:
derived ()
{
// only initialize derived 's members
}
virtual ~derived ()
{
// only release derived 's members
}
virtual bool initialize(/* whatever goes here */)
{
// do your further initialization here
// return success/failure
}
};
An example of (2) is:
class accessible
{
private:
class accessible_impl
{
protected:
accessible_impl()
{
// only initialize accessible_impl's members
}
public:
static accessible_impl* create_impl(/* params for this factory func */);
virtual ~accessible_impl()
{
// only release accessible_impl's members
}
virtual bool initialize(/* whatever goes here */) = 0;
};
accessible_impl* m_impl;
public:
accessible()
{
m_impl = accessible_impl::create_impl(/* params to determine the exact type needed */);
if (m_impl)
{
m_impl->initialize(/* ... */); // add any initialization checking you need
}
}
virtual ~accessible()
{
if (m_impl)
{
delete m_impl;
}
}
/* Other functionality of accessible, which may or may not use the impl class */
};
Approach (2) uses the Factory pattern to provide the appropriate implementation for the accessible class (which will provide the same interface as your base class). One of the main benefits here is that you get initialization during construction of accessible that is able to make use of virtual members of accessible_impl safely.
For C++, section 12.7, paragraph 3 of the Standard covers this case.
To summarize, this is legal. It will resolve to the correct function to the type of the constructor being run. Therefore, adapting your example to C++ syntax, you'd be calling BaseObject::LoadState(). You can't get to ChildObject::LoadState(), and trying to do so by specifying the class as well as the function results in undefined behavior.
Constructors of abstract classes are covered in section 10.4, paragraph 6. In brief, they may call member functions, but calling a pure virtual function in the constructor is undefined behavior. Don't do that.
If you have a class as shown in your post, which takes an XElement in the constructor, then the only place that XElement could have come from is the derived class. So why not just load the state in the derived class which already has the XElement.
Either your example is missing some fundamental information which changes the situation, or there's simply no need to chain back up to the derived class with the information from the base class, because it has just told you that exact information.
i.e.
public class BaseClass
{
public BaseClass(XElement defintion)
{
// base class loads state here
}
}
public class DerivedClass : BaseClass
{
public DerivedClass (XElement defintion)
: base(definition)
{
// derived class loads state here
}
}
Then your code's really simple, and you don't have any of the virtual method call problems.
For C++, read Scott Meyer's corresponding article :
Never Call Virtual Functions during Construction or Destruction
ps: pay attention to this exception in the article:
The problem would almost certainly
become apparent before runtime,
because the logTransaction function is
pure virtual in Transaction. Unless it
had been defined (unlikely, but
possible) the program wouldn't link: the linker would be unable to find the necessary implementation of Transaction::logTransaction.
Usually you can get around these issues by having a greedier base constructor. In your example, you're passing an XElement to LoadState. If you allow the state to be directly set in your base constructor, then your child class can parse the XElement prior to calling your constructor.
public abstract class BaseObject {
public BaseObject(int state1, string state2, /* blah, blah */) {
this.State1 = state1;
this.State2 = state2;
/* blah, blah */
}
}
public class ChildObject : BaseObject {
public ChildObject(XElement definition) :
base(int.Parse(definition["state1"]), definition["state2"], /* blah, blah */) {
}
}
If the child class needs to do a good bit of work, it can offload to a static method.
In C++ it is perfectly safe to call virtual functions from within the base-class - as long as they are non-pure - with some restrictions. However, you shouldn't do it. Better initialize objects using non-virtual functions, which are explicitly marked as being such initialization functions using comments and an appropriate name (like initialize). If it is even declared as pure-virtual in the class calling it, the behavior is undefined.
The version that's called is the one of the class calling it from within the constructor, and not some overrider in some derived class. This hasn't got much to-do with virtual function tables, but more with the fact that the override of that function might belong to a class that's not yet initialized. So this is forbidden.
In C# and Java, that's not a problem, because there is no such thing as a default-initialization that's done just before entering the constructor's body. In C#, the only things that are done outside the body is calling base-class or sibling constructors i believe. In C++, however, initializations done to members of derived classes by the overrider of that function would be undone when constructing those members while processing the constructor initializer list just before entering the constructors body of the derived class.
Edit: Because of a comment, i think a bit of clarification is needed. Here's an (contrived) example, let's assume it would be allowed to call virtuals, and the call would result in an activation of the final overrider:
struct base {
base() { init(); }
virtual void init() = 0;
};
struct derived : base {
derived() {
// we would expect str to be "called it", but actually the
// default constructor of it initialized it to an empty string
}
virtual void init() {
// note, str not yet constructed, but we can't know this, because
// we could have called from derived's constructors body too
str = "called it";
}
private:
string str;
};
That problem can indeed be solved by changing the C++ Standard and allowing it - adjusting the definition of constructors, object lifetime and whatnot. Rules would have to be made to define what str = ...; means for a not-yet constructed object. And note how the effect of it then depends on who called init. The feature we get does not justify the problems we have to solve then. So C++ simply forbids dynamic dispatch while the object is being constructed.
I am a bit confused, i was reading this C++ Constructor/Destructor inheritance, and so it says constructors and destructors are not inherited from the base class to the derived class but the constructors and destructors are called when i create a derived object. So is the constructors and destructors of the base class data members of the inherited classes?
Constructors and destructors are very special animals; in fact, the Standard identifies them as "Special Member Functions."
All the things that are weird and unique about constructors and destructors (for example, the fact that they don't have "names" and the fact that they aren't "inherited") is really quite irrelevant to almost all programming and programmers. Here is what you need to know:
Constructors and destructors are not member variables (obviously) -- they are (special) member functions.
When you derive from a base class, some constructor of the base class is going to be called. Which constructor depends on how you've written your code. If you don't explicitly specify which constructor to call, the default constructor will be called. This happens in your derived object's initialization list, even if you haven't written one.
You may specify another constructor through an initialization list, only:
class Bar : public Foo
{
public:
Bar()
:
Foo (1, 2, 3)
{
}
};
Here, Bar's initialization list specifies a constructor on Foo which takes 3 parameters convertible from integrals. One such constructor might be:
class Foo
{
public:
Foo (int a, long b, unsigned c)
:
mA (a),
mB (b),
mC (c)
{
}
private:
int mA;
long mB;
unsigned mC;
};
Back to the Bar example above. By the time the initialization list is done executing, and before the body of Bar's constructor starts, all of Bar's base classes and member variables have already been instantiated and initialized. This is why the only way to specify some constructor for Foo other than the default constructor is through an initialization list -- which, in turn, is why you must have an initialization list if the base class has no default constructor available.
Question: If constructors and destructors are not inherited, then why are they called when instantiating a derived type?
Answer: Because constructors are what initialize objects, and a derived type has an IS-A relationship with the base type.
Consider Foo and Bar above again. Bar derives from Foo, so in a sense Bar IS A Bar. It's more than just a Foo, it's got stuff that Foo doesn't have; but it has all the Foo-ness. Since a Bar object is in part a Foo, that Foo-ness has to be initialized. Since all initialization ob objects is done through a constructor, Foo's constructor must be called.
So, constructors and destructors aren't inherited in the sense of overloading -- but the constructors of the base class will be called. They have to be. Otherwise the Fooness of a Bar object could never come to be.
When you are deriving from a base class, something that you will often want to do is pass around a pointer to the base class. In fact, you may not need a pointer to the derived type at all in many cases. This is especially true when designing abstract interfaces.
There is a nasty problem that can come up when you do this and haven't taken all the needed preperations. Consider:
class Foo
{
public:
std::string mS;
};
class Bar : public Foo
{
public:
long mArray[0xFFFF]; // an array of 65K longs
};
int main()
{
Foo* thingy = new Bar; // Totally OK
// ... do stuff...
delete thingy; // WHOOPS! Memory leak!
}
Above in the delete call we're deleting through a base class pointer. The Foo destructor (which is implicit) is properly called, but the Bar destructor is not -- leaving that huge array of 65K longs leaked.
To fix this, we need to give Foo a virtual destructor:
class Foo
{
public:
std::string mS;
virtual ~Foo() {}
};
This doesn't do much, but it does one critical thing: it sets up polymorphism so that when we call the destructor (implicitly), the virtual override will get called.
This is a critical step when designing a class hierarchy. If you think there is any chance that people will pass around pointers to the base class, you should have a virtual destructor in the base class. In fact, I would suggest that in almost every case you should have a virtual destructor even if you don't think people will use it this way.
No. As you said, constructors and destructors are not inherited (by the way, the assignment operator isn't either). It would be logically flawed if they were inherited, right? Constructors (and destructors) are specific for that exact class; and since the derived class usually has something specific and new, the base constructor is not enough to initialize the inherited class objects.
So why is the base constructor called when creating an object of the child class?
Well, every derived object has a sub-object - which is the actual object of the parent class (I hope this sentence wasn't difficult to understand).
The compiler will:
1) locate the constructor of the derived class whose list of initializers best fits the arguments passed, but not execute it;
2) execute the constructor of the base class to create the sub-object;
3) execute the constructor of the derived class, to create the actual object.
I hope this is clear; you can find a much more detailed explanation in the answer above :)
I have a purely virtual class defined as such:
class BaseClass {
protected:
const int var;
public:
void somefun() = 0; // what I mean by a purely virtual class
// stuff...
};
If I don't add a constructor defined as such:
BaseClass(const int & VAR) : var(VAR) {};
that I would have to subsequently use in ever derived class, my derived class can't initialize the const variable var to whichever value it wants to. Now I actually understand what's going on here. Before constructing a derived class, a constructor of the base class is called, at which point const member variables must be initialized. My question is not a "how do I make my code work" kind of question, that's already been done. My question is about why the compiler thinks it's necessary. For a purely virtual class, shouldn't I be allowed to write something like:
class DerivedClass : BaseClass {
public:
DerivedClass() : var(SOME_VALUE) {};
}
If the compiler knows that a call to a BaseClass constructor will necessarily be followed by a call to some derived class constructror (since an object of abstract type can never be instantiated) shouldn't it give us a bit more leeway?
Is this all a consequence of how C++ chooses to get around the Diamond problem? Even if that was the case, shouldn't the compiler at least somehow allow for the possibility that const member variable of purely virtual functions will be defined in derived classes? Is that too complicated or does that mess with the C++ solution to the Diamond problem?
Thanks for the help everyone.
It's not "purely virtual" (whatever you mean by that) - it contains a data member.
Class members can only be initialised by the initialiser list of a constructor of that class, not of a derived class. That's how object initialisation is specified: all members that are initialised, are initialised before the constructor body begins.
Constant objects must be initialised, since they can't be assigned a value later.
Therefore, a class with a constant data member must initialise it in each constructor.
For a purely virtual class, shouldn't I be allowed to write something
like
No, but you can(and in this case should) write something like this:
class DerivedClass : BaseClass {
public:
DerivedClass() : BaseClass(SOME_VALUE) {};
};
The construction of an object occurs in a specific order. The base class must be fully constructed before the constructor of a derived class is run, so that the derived constructor is working with a fully formed and valid base object. If the initialization of base member variables were put off until the construction of the derived class, this invariant would be broken.