sten
sten

Reputation: 7476

virtual methods and constructors?

I have chicken<->egg problem.
I want to create interface for a container classes, so that I can force implementation of specific attr-accessors and other methods and at the same time I want to be able to call those methods from the Containers constructors.
But as we know calling virtual method from Constructor will call the Base class methods, because of the sequence at which the constructors in hierarchy are called.
So the problem is I need virtual methods to force implementation, but that is the thing I can't call in constructor.
EDIT: I want when I have to implement Container class (C1,C2...) to be forced to implement specific methods AND second I want to be able to use those methods in the Container-constructors. In simple terms I want to implement INTERFACE requirement, declaration-only-mixin. thanks
How do you solve this problem ?
Below is code sample.

#include <iostream>
using namespace std;

class Base {
public: 
    virtual void myvirt() { cout << "Base::virt()" << endl; };
};

class C1 : public Base {
 public:
    C1() {cout << "C1()" << endl; C1::myvirt(); };
    C1(int i) { cout << "C1(int)" << endl; }
    void myvirt() { cout << "C1::virt" << endl;}
};


class C2 : public Base {
 public:
    C2() {cout << "C2()" << endl; C2::myvirt();};
    C2(int i) { cout << "C2(int)" << endl; }
    void myvirt() { cout << "C2::virt" << endl;}
};

template<class C = C1>
class Sc: public C {
 public:
    Sc() : C() { cout << "Sc()" << endl; };
    Sc(int n): C(n)  { cout << "Sc(int)" << endl; };

};


int main() {
    Sc<C2>  $sx(12);
    return 0;
}

Just as I'm asking is there some way to force implementation in descendant classes of specific Constructors(). Something like "virtual Constructors".

Upvotes: 1

Views: 163

Answers (2)

tzuchien.chiu
tzuchien.chiu

Reputation: 700

You should not call virtual functions during Construction or Destruction in the first place. It's simply not a good practice.

Excerpt from Item 9 of Effective C++, 3rd Edition:

There's a good reason for this seemingly counterintuitive behavior. 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. That would be a non-stop ticket to undefined behavior and late-night debugging sessions. Calling down to parts of an object that have not yet been initialized is inherently dangerous, so C++ gives you no way to do it.

http://www.artima.com/cppsource/nevercall.html

Upvotes: 3

David Schwartz
David Schwartz

Reputation: 182769

Just make the constructor trivial and then after the constructor has returned, call some kind of initialization function to complete the construction of the object. You can also use the clone idiom, depending on how you want to decide what kind of object to construct.

You can also have a wrapper class whose constructor first constructs the inner class and then calls its virtual initialization function.

Update: You can wrap like this:

 Class Wrapper : public Inner
 {
        public:
        Wrapper(...) : Inner(...)
        {
            init();
        }
        virtual ~Wrapper();
 }

Now you can just do

 Wrapper foo(whatever);

And you can use foo just like an Inner.

Upvotes: 5

Related Questions