Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call derived class virtual method from base class constructor?

Tags:

c++

c++11

class MyClass1
{
public:
  MyClass1()
  {
    init();
  }
  virtual void init()
  {
    printf("MyClass1 init");
  }
}

class MyClass2 : public MyClass1
{
public:
  virtual void init()
  {
    printf("MyClass2 init");
  }
}

int main()
{
  MyClass2 *obj = new MyClass2();
  return 0;
}

I would like for this to result

"MyClass2 init"

But it show the message Actually

"MyClass1 init"

How to call derived class virtual method from base class constructor ?

=== update1 ===

class MyClass1
{
public:
  MyClass1()
  {
    init();
  }
  virtual void init()
  {
    printf("MyClass1 init");
  }
}

class MyClass2 : public MyClass1
{
public:
  MyClass2()
    : MyClass1()
  {
  }

  virtual void init()
  {
    printf("MyClass2 init");
  }
}

I hope MyClass2 override MyClass1 init method But it still show "MyClass1 init"

How C++ works like java/C# override method ?

=== update2 ===

class MyClass1
{
public:
  MyClass1()
  {
    init();   <--- can't work like test method ??? 
  }
  void test()
  {
    init();   <--- work fine
  }
  virtual void init()
  {
    printf("MyClass1 init");
  }
}

class MyClass2 : public MyClass1
{
public:
  MyClass2()
    : MyClass1()
  {
  }

  virtual void init()
  {
    printf("MyClass2 init");
  }
}

I know obj->init() will call MyClass2::init.
but I hope C++ can run in Constructor method.

Although obj->init() can be resolved.
But I hope that the code can write a little less.
Some people forget to call init().

Java/C# can Write less do more. But C++ can't.... This is very frustrating.

like image 633
Flash Avatar asked Oct 27 '25 07:10

Flash


2 Answers

Clearly during the construction of MyClass2, MyClass1's constructor will be called first, that's base class parts of derived class objects are constructed before derived class parts are. Even when you clearly try to create object of MyClass2, but during base class construction, virtual functions never go down into derived classes.

Because base class constructors execute before derived class constructors, derived class data members have not been initialized when base class constructors run. If virtual functions called during base class construction went down to derived classes, the derived class functions would almost certainly refer to local data members, but those data members would not yet have been initialized which will cause undefined behavior.

Refer to your classes, why do you have virtual init in the first place? Constructors should do the work respectively.

How to call derived class virtual method from base class constructor ?

It's bad idea, should never ever do that!

class MyClass1
{
public:
  virtual ~MyClass1() { }
  virtual void doSomething()
  {
    printf("MyClass1 init");
  }
};

class MyClass2 : public MyClass1
{
public:
  virtual void doSomething()
  {
    printf("MyClass2 init");
  }
};

int main()
{
  MyClass1*obj = new MyClass2();
  obj->doSomething();
  delete obj;
  return 0;
}
like image 111
billz Avatar answered Oct 28 '25 23:10

billz


Generally speaking, you can't. That's because the MyClass2 constructor has not yet been run, so if MyClass2::init() were to be called, any member variable would be uninitialized. Until this constructor is started the object, for virtual purposes, is considered to be a MyClass1 instance.

For example:

class MyClass2 : public MyClass1
{
private:
    std::string xxx;
public:
    virtual void init()
    {
        xxx = "ops!"; //undefined if called from base class constructor
    }
};

The assignment to xxx will render undefined behavior, because its constructor has not yet been run.

Given your lack of ending ; I'm guessing your background in Java/C#. These languages have implemented this issue differently, but that's just how C++ works.

like image 28
rodrigo Avatar answered Oct 28 '25 23:10

rodrigo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!