C ++ virtual function from constructor

Why is โ€œ0โ€ printed in the following example, and what should change to print โ€œ1โ€ as I expected?

#include <iostream> struct base { virtual const int value() const { return 0; } base() { std::cout << value() << std::endl; } virtual ~base() {} }; struct derived : public base { virtual const int value() const { return 1; } }; int main(void) { derived example; } 
+56
c ++ constructor oop class virtual
Jan 30 '09 at 17:37
source share
7 answers

Because base built first and has not yet "matured" in derived . It cannot invoke methods on an object if it cannot guarantee that the object is already properly initialized.

+89
Jan 30 '09 at 17:41
source share
โ€” -

When a derived object is constructed, before the body of the constructor of the derived class is called the constructor of the base class, it must complete. Before the constructor of a derived class is called the dynamic type of the object being built, it is an instance of the base class, not an instance of the derived class. For this reason, when calling a virtual function from the constructor, you can only call the redefinition of the virtual functions of the base class.

+20
Jan 30 '09 at 17:43
source share

Actually, there is a way to get this behavior. "Every software problem can be solved with a level of indirection."

 /* Disclaimer: I haven't done C++ in many months now, there might be a few syntax errors here and there. */ class parent { public: parent( ) { /* nothing interesting here. */ }; protected: struct parent_virtual { virtual void do_something( ) { cout << "in parent."; } }; parent( const parent_virtual& obj ) { obj.do_something( ); } }; class child : public parent { protected: struct child_virtual : public parent_virtual { void do_something( ) { cout << "in child."; } }; public: child( ) : parent( child_virtual( ) ) { } }; 
+9
Jan 31 '09 at 8:07
source share

You should not polymorphically call virtual methods from the constructor. Instead, you can call them after creating the object.

Your code can be written as follows

 struct base { virtual const int value() const { return 0; } base() { /* std::cout << value() << std::endl; */ } virtual ~base() {} }; struct derived : public base { virtual const int value() const { return 1; } }; int main(void) { derived example; std::cout << example.value() << std::endl; } 
+4
Jan 31 '09 at 1:15
source share

The question of how this works is an element of frequently asked questions .

To summarize, while the class T is being built, the dynamic type is T , which prevents virtual calls to implement functions of the derived class, which, if allowed, can execute code before the corresponding class invariant has been set (a common problem in Java and C # but C ++ is safe in this regard).

The question of how to perform initialization with derivative derivatives in the constructor of the base class is also an element of frequently asked questions , directly following the previously mentioned.

Summing up using static or dynamic polymorphism can pass the corresponding function implementations to the constructor of the base class (or class).

One way to do this is to pass a "parts factory" object where this argument can be disabled. For example, the generic Button class can pass a button creation API function to its Widget base class constructor, so that this constructor can create the correct API level object.

+3
Jan 26 '14 at 21:14
source share

General rule: you do not call a virtual function from the constructor.

0
Jan 30 '09 at 17:40
source share

In C ++, you cannot call the virtual / overriden method from the constructor.

Now there is a good reason why you can do this. As a โ€œbest practice in softwareโ€, you should avoid calling additional methods from your constructor, not even virtual as much as possible.

But there is always an exception to the rule, so you can use the "pseudo constructor method" to mimic them:

 #include <iostream> class base { // <constructor> base() { // do nothing in purpouse } // </constructor> // <destructor> ~base() { // do nothing in purpouse } // </destructor> // <fake-constructor> public virtual void create() { // move code from static constructor to fake constructor std::cout << value() << std::endl; } // </fake-constructor> // <fake-destructor> public virtual void destroy() { // move code from static destructor to fake destructor // ... } // </fake-destructor> public virtual const int value() const { return 0; } public virtual void DoSomething() { // std:cout << "Hello World"; } }; class derived : public base { // <fake-constructor> public override void create() { // move code from static constructor to fake constructor std::cout << "Im pretending to be a virtual constructor," << std::endl; std::cout << "and can call virtual methods" << std::endl; } // </fake-constructor> // <fake-destructor> public override void destroy() { // move code from static destructor to fake destructor std::cout << "Im pretending to be a virtual destructor," << std::endl; std::cout << "and can call virtual methods" << std::endl; } // </fake-destructor> public virtual const int value() const { return 1; } }; int main(void) { // call fake virtual constructor in same line, after real constructor derived* example = new example(); example->create(); // do several stuff with your objects example->doSomething(); // call fake virtual destructor in same line, before real destructor example->destroy(); delete example(); } 

As a plus, I recommend programmers to use "struct" only for field structures and "class" for structures with fields, methods, constructors, ...

-four
Mar 28 '11 at 17:10
source share



All Articles