I know that within constructor of Base class - when calling virtual method - the Base method is called, not derived - see Calling virtual functions inside constructors.
My question is related to this topic. I've just wondered what happens if I call virtual method in Derived class constructor - but before constructing Base part. I mean calling virtual method to evaluate Base class constructor argument, See code:
class Base {
public:
Base(const char* name) : name(name) {
cout << "Base():" << name << endl;
}
virtual const char* getName() {
cout << "Base::getName()" << endl;
return "Base";
}
protected:
const char* name;
};
class Derived : public Base {
public:
Derived() : Base(getName()) {
cout << "Derived():" << name << endl;
}
virtual const char* getName() {
cout << "Derived::getName()" << endl;
return "Derived";
}
};
int main() {
Derived d;
}
Compiler g++ (4.3.x-4.5x versions) output is:
Derived::getName()
Base():Derived
Derived():Derived
However I'd expect:
Base::getName()
Base():Base
Derived():Base
This does not look wrong - but consider this example, which produces segmentation fault
:
class Derived : public Base {
public:
Derived() : Base(getName()), name(new string("Derived")) {
cout << "Derived():" << Base::name << endl;
}
virtual const char* getName() {
cout << "Derived::getName()" << endl;
return name->c_str();
}
private:
string* name;
};
Please answer: Is this correct g++ behavior? What C++ standard says about that? Maybe it is undefined behavior?
[UPDATE1] I take into consideration Robert and Oli answers - and I changed my first example. Then it getName() is called "virtual" - and it produces Segmentation Fault. Please answer my question to this part too.
const char* virtualGetName(Base* basePtr)
{
return basePtr->getName();
}
class Derived : public Base {
public:
Derived() : Base(virtualGetName(this)) {
cout << "Derived():" << Base::name << endl;
}
virtual const char* getName() {
cout << "Derived::getName()" << endl;
return "Derived";
}
};
All of your examples exhibit undefined behavior. The C++ language standard states (C++11 §12.6.2/13):
Member functions (including virtual member functions) can be called for an object under construction. Similarly, an object under construction can be the operand of the
typeid
operator or of adynamic_cast
.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.
You are calling the member function getName()
from the initialization list (the ctor-initializer) of the Derived
class constructor. This member function call must take place before the initializer for Base
completes (the mem-initializer for Base
) because it is an argument to the initializer itself.
Therefore, the behavior is undefined.
As a rule, Never Call Virtual Functions during Construction or Destruction.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With