我想知道我应该如何为我的第四课打电话给我的构造函数。 A类是基类,B类和C类继承它。
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)
{
}
现在我的第四个类继承了B类和C类 我该如何为我的班级D调用构造函数?
我试过这种方式,但我得到“没有匹配函数来调用ClassB :: ClassB()â”
ClassD::ClassD(const string &nam, const string& ide, double bal)
:ClassA(nam, ide, bal), ClassB(), ClassC()
{
}
答案 0 :(得分:2)
这里不可见的是你是使用普通还是虚拟继承。这对你调用构造函数有很大的影响:
如果您使用普通继承,则ClassA
的每个实例中都有两个 ClassD
个实例。一个作为ClassB
实例的一部分,另一个作为ClassC
实例的一部分。因此,每个中间类都使用自己的构造函数调用构造自己的基本实例。
然而,这很可能不是您想要达到的目标。除了作为结合大脑的最可靠方法之一之外,你会遇到许多问题,其中最少的是几乎任何从ClassA
的实例访问ClassD
成员的尝试都将由于歧义而产生错误。编译器根本不知道要从哪两个实例中查找成员。
如果使用虚拟继承,则对象中只有一个ClassA
实例。因此,ClassB
的构造函数和ClassC
的构造函数都不会构造共享库,ClassA
如果构造它们将构造两次。相反,ClassA
在调用其他两个基本构造函数之前直接从ClassD
的构造函数构造,因此您需要将ClassA()
的调用添加到ClassD
的初始化列表中如果默认构造函数不能做。
回应你的评论:
您可以将ClassA
的默认构造函数添加到ClassB
和ClassC
的构造函数中。然后,ClassD
可以调用ClassA
的完整构造函数,而您不必通过ClassB
和ClassC
的构造函数转发参数。只要您只构造ClassD
的对象,就永远不会调用ClassA
的默认构造函数,即使它必须存在于ClassB
和{{1的默认构造函数的定义中}}
请考虑以下代码:
ClassC
该程序的输出是
#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);
}
正如您所看到的,即使A::A(int)
B::B()
C::C()
D::D(int)
和A::A()
是默认构造且不需要传递参数,也永远不会调用B
。 C
直接从班级A::A(int)
调用。
答案 1 :(得分:1)
你应该声明为:
class ClassB: public virtual Class A
{
...
};
class ClassC: public virtual Class A
{
...
};
class ClassD: public ClassB, ClassC
{
...
};