1

I am wondering how Im supposed to call my constructor for my 4th class. Class A is the base class and Class B and C inherit it.

ClassA::ClassA( const string &nam, const string &ide, double bal)
        :name(nam), id(ide), balance(bal)
{
}

ClassB::ClassB(const string &nam, const string &ide, double bal)
        :ClassA(nam, ide, bal)
{
}
 ClassC::ClassC(const string &nam, const string &ide, double bal)
                :ClassA(nam, ide, bal)
{
}

now my 4th class inherits both class B and Class C how am I supposed to call constructor for my class D?

I tried it this way but I get "no matching function for call to ClassB::ClassB()â"

ClassD::ClassD(const string &nam, const string& ide, double bal)
        :ClassA(nam, ide, bal), ClassB(), ClassC()
{
}
user3582405
  • 21
  • 2
  • 3
  • Since no one else, including the linked question, addresses the actual *error message* you're getting; I will. Do *either* of your `ClassB` or `ClassC` constructors look like they take **no** parameters?? Yeah, *neither* do. So why are you invoking `ClassB()` and `ClassC()` ? use their declared constructors. That said, everything in the linked question and the posted answer(s) applies, so read them carefully. – WhozCraig Apr 29 '14 at 09:58
  • Im just very confused as to which constructor to call and which ones to not call? I understand I'm supposed to call ClassA constructor because it's the base class, but does it mean I dont call class B and C constructors at all? and if I do, do I leave the arguments empty, which is why I think Im getting that error. *All the virtual Inheritance statements are included in my .h files. – user3582405 Apr 29 '14 at 19:05

2 Answers2

6

What is not visible here is whether you used normal or virtual inheritance. This has a huge effect on your calling of the constructors:

  1. If you use normal inheritance, you have two instances of ClassA within each instance of ClassD. One as a part of the ClassB instance, the other as a part of the ClassC instance. As such, each of the intermediate classes constructs its own base instance with its own constructor call.

    However, this is most likely not what you want to achieve. Apart from being one of the surest ways to knot brains, you will run into many issues with this, the least of which is that almost any attempt to access a member of ClassA from an instance of ClassD will generate an error due to ambiguity. The compiler simply does not know from which of the two instances to look up the member.

  2. If you use virtual inheritance, you only have a single instance of ClassA in your object. As such, neither the constructor of ClassB nor the constructor of ClassC will construct the shared base, ClassA would be constructed twice if they did. Instead, ClassA is constructed directly from the constructor of ClassD before it calls the other two base constructors, so you need to add a call to ClassA() to the initializer list of ClassD if the default constructor won't do.


In response to your comment:
You can add a default constructor to ClassA which you call from the constructors of ClassB and ClassC. ClassD can then call the full constructor of ClassA and you don't have to forward the arguments through the constructors of ClassB and ClassC. As long as you only construct objects of ClassD, the default constructor of ClassA is never called, even though it must be present for the definition of the default constructors of ClassB and ClassC.

Consider the following code:

#include <iostream>

class A {
    public:
        A() { std::cout << "A::A()\n"; }    //Not used, but required.
        A(int) { std::cout << "A::A(int)\n"; }
};

class B : public virtual A {
    public:
        B() { std::cout << "B::B()\n"; }
        B(int) : A(1) { std::cout << "B::B(int)\n"; }    //Not required.
};

class C : public virtual A {
    public:
        C() { std::cout << "C::C()\n"; }
        C(int) : A(1) { std::cout << "C::C(int)\n"; }    //Not required.
};

class D : public B, public C {
    public:
        D(int) : A(1) { std::cout << "D::D(int)\n"; }
};

int main() {
    D foo(1);
}

The output of this program is

A::A(int)
B::B()
C::C()
D::D(int)

As you can see, A::A() is never called even though B and C are default constructed and don't need to pass through the parameter. A::A(int) is called directly from class D.

cmaster - reinstate monica
  • 38,891
  • 9
  • 62
  • 106
  • I included virtual inheritance for my class B and C. I'm just having trouble with the ClassD constructor. ClassB and C ake the exact same parameters as classA so they call it. So now I have a 4th class taking the same parameters, do I call classA constructor with B and C empty? or just A and omit B and C? – user3582405 Apr 29 '14 at 19:04
  • I have added my response to your comment directly to the answer. I hope the example is illustrative enough. – cmaster - reinstate monica Apr 30 '14 at 00:48
0

you should declare as:

class ClassB: public virtual Class A
{
  ...
};
class ClassC: public virtual Class A
{
  ...
};
class ClassD: public ClassB, ClassC
{
...
};
Dr. Debasish Jana
  • 6,980
  • 4
  • 30
  • 69