Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do all derived classes from a hierarchy require access to the virtual base class?

When I try to compile the following code:

class A {
public:
    A(int v) : virt(v) { }
    int virt;
    int getVirt(void) const { return virt; }
};

class B : private virtual A {
protected:
    B(int v) : A(v) { }
    using A::getVirt;
};

class C : public B, private virtual A {
protected:
    C(int v) : A(v), B(v) { }
    using A::getVirt;
};

class D : public C {
public:
    D(void) : C(3) { }
    using C::getVirt;
};

#include <iostream>

int main(int argc, char *argv[]) {
    D d;
    std::cout << "The number is: " << d.getVirt() << std::endl;

    return 0;
}

I get an error about D not instantiating A; is that correct? If a virtual base is embedded in the hierarchy do all derived classes also need to derive from that base, virtually, so they can call the parametric constructor of the virtual base?

BTW, here are the errors produced by G++:

Main.cpp: In constructor ‘D::D()’:
Main.cpp:22:18: error: no matching function for call to ‘A::A()’
Main.cpp:22:18: note: candidates are:
Main.cpp:3:5: note: A::A(int)
Main.cpp:3:5: note:   candidate expects 1 argument, 0 provided
Main.cpp:1:7: note: A::A(const A&)
Main.cpp:1:7: note:   candidate expects 1 argument, 0 provided
like image 248
TimeHorse Avatar asked Mar 15 '13 20:03

TimeHorse


People also ask

What are the requirements of virtual base class?

Virtual base class in C++ Virtual base classes are used in virtual inheritance in a way of preventing multiple “instances” of a given class appearing in an inheritance hierarchy when using multiple inheritances. Need for Virtual Base Classes: Consider the situation where we have one class A .

What does a base class have access to in its derived class?

A derived class can access all the non-private members of its base class. Thus base-class members that should not be accessible to the member functions of derived classes should be declared private in the base class. Constructors, destructors and copy constructors of the base class.

Which of the following option is true about virtual base classes?

When employing multiple inheritance, virtual base classes are used to prevent several "instances" of a particular class from appearing in an inheritance hierarchy. Hence option (b) is the correct answer. A virtual base class is used to avoid multiple copies of base class in the derived class.

Which type of inheritance need virtual base classes?

Virtual classes are primarily used during multiple inheritance. To avoid, multiple instances of the same class being taken to the same class which later causes ambiguity, virtual classes are used.


2 Answers

That has nothing to do with access control (at least not primarily). Rather, you have to understand how virtual bases work: The virtual base subobject is initialized by the most derived class. Since you don't mention A in the constructor initializer list of D, the default constructor is tried, but doesn't exist.

To fix this, initalize A properly in D:

 D() : A(3), C(3) { }

When you say A(3), name lookup is performed according to 12.6.2/2:

In a mem-initializer-id an initial unqualified identifier is looked up in the scope of the constructor’s class and, if not found in that scope, it is looked up in the scope containing the constructor’s definition.

As Drew Dorman rightly points out, you can force a direct path to the virtual base class by calling it ::A and thus obtaining the desired access.

like image 153
Kerrek SB Avatar answered Nov 04 '22 08:11

Kerrek SB


As Kerrek SB mentions, you need to initialize A in the constructor for D.

However, you must also explicitly tell the compiler that you are not accessing A from its (privately) derived context by using the scope operator.

class D : public C {
public:
    D(void) : ::A(3), C(3) { }
//            ^^ Access this constructor from a global context
    using C::getVirt;
};

This also means that your constructor must be public, as is already the case with your code.

like image 24
Drew Dormann Avatar answered Nov 04 '22 09:11

Drew Dormann