virtual classes confusion

I have this design (the basic dreaded diamond):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class base{ 
public:
    base(const char* label) : m_label(label){};
    virtual ~base(){};

    void init(){};
    const char *get_label() { return m_label; };
protected:
    const char *m_label;
};

class O1 : public virtual base
 {
 public:
     O1(const char *label) : base(label){};
     virtual ~O1(){};

};

class O2 : public virtual base
{
 public:
     O2(const char *label) : base(label){};
     virtual ~O2(){};
};

class O12 : public O1, public O2
 {
 public:
     O12(const char *label) : ???(label){};
     virtual ~O12(){};

};


The ??? is the problem. Both with and without explicitly calling an inherited constructor fail. The compiler gripes about not finding a matching constructor for base. Unless I change "???" to "base". Then it gripes about not finding a constructor for one of the other classes (O1 or O2). Is it (perchance) because of the base constructor's arg?

Any pointers to getting something like this working?

TIA

ken



Virtual base objects need to be initialized before the other objects, but since you don't have a default constructor, you still need to call the other parent objects explicitly after the base object.

1
2
3
4
5
6
7
class O12 : public O1, public O2
 {
 public:
     O12(const char *label) : base(label), O1(label), O2(label) {};
     virtual ~O12(){};

};


The base class will only be initialized once.

See also these SO threads:
https://stackoverflow.com/questions/17125596/c-virtual-inheritance-initializer-list
https://stackoverflow.com/questions/4849289/virtual-base-class-and-initialization-lists
Last edited on
Thanks, Ganado. After I read your reply, I found this as well @https://www.cprogramming.com/tutorial/virtual_inheritance.html :


Because there is only a single instance of a virtual base class that is shared by multiple classes that inherit from it, the constructor for a virtual base class is not called by the class that inherits from it (which is how constructors are called, when each class has its own copy of its parent class) since that would mean the constructor would run multiple times. Instead, the constructor is called by the constructor of the concrete class. In the example above, the class radio directly calls the constructor for storable. If you need to pass any arguments to the storable constructor, you would do so using an initialization list, as usual:

radio::radio ()
: storable( 10 ) // some value that storable needs
, transmitter()
, receiver()
{}


It was the concrete part that I didn't get at first. Specifically, the base constructor is called first, by the merged class o12. The gotcha to watch out for is that neither o1 nor 02 mess around with base in a way that would adversely affect either of them.

ken
Topic archived. No new replies allowed.