考虑以下事项:
#include <iostream>
#include <string>
using namespace std;
class A {
public:
A(const char* sName) //conversion constructor
: _sName(sName) {cout<<"(1)"<<endl;} ;
A(const A& s) {cout<<"(2)"<<endl;} //copy constructor
virtual ~A() {cout<<"(3)"<<endl;} //destructor
void f1() {cout<<"(4)"<<endl; f2();} //Notice two commands!
virtual void f2() =0;
private:
string _sName;
};
class B1: virtual public A {
public:
B1(const char* sAName, const char* sSName)
: _sName1(sAName), A(sSName) {cout<<"(5)"<<endl;}
B1(const B1& b1) : A(b1) {cout<<"(6)"<<endl;}
~B1() {cout<<"(7)"<<endl;}
virtual void f1() {cout<<"(8)"<<endl;}
virtual void f2() {cout<<"(9)"<<endl; f3();}
virtual void f3() {cout<<"(10)"<<endl;}
private:
string _sName1;
};
class B2: virtual public A {
public:
B2(const char* sAName, const char* sSName)
: _sName2(sAName), A(sSName) {cout<<"(11)"<<endl;}
B2(const B2& b2) : A(b2) {cout<<"(12)"<<endl;}
~B2() {cout<<"(13)"<<endl;}
virtual void f3() {f1(); cout<<"(14)"<<endl;}
private:
string _sName2;
};
class C: public B1, public B2 {
public:
C () : A(" this is A ") , B1(" this is " , " B1 ") , B2 (" this is " , " B2 ") {}
C (const C& c) : A(c) , B1(c) , B2(c) {}
~C() {cout<<"(15)"<<endl;}
virtual void f1() {A::f1(); cout<<"(16)"<<endl;}
void f3 () {cout<<"(17)"<<endl;}
};
int main() {
/* some code */
return 0;
}
如您所见,我在class C
中添加了C的Ctor(构造函数)的实现。我不清楚的是,如果B1在Ctor中为我做这项工作,为什么我还需要从C到A的向上转换?
意思是,如果我把C的Ctor写成:
C () : A(" this is A ") , B1(" this is " , " B1 ") , B2 (" this is " , " B2 ") {}
为什么我不能写:
C () : B1(" this is " , " B1 ") , B2 (" this is " , " B2 ") {}
谢谢,
RONEN
答案 0 :(得分:2)
简而言之,因为它符合标准要求:你必须在最受欢迎的课程中初始化虚拟基础。
一个更详细的答案,这是因为你只有一个基础子对象用于虚拟基础,这个子对象可能在不同的基类中被不同地初始化。例如。在你的例子中
C () : B1(" this is " , " B1 ") , B2 (" this is " , " B2 ") {}
您希望将什么价值传递给A ctor,“B1”或“B2”?
答案 1 :(得分:2)
虚拟基础的构造函数在非虚拟的ansestors ctor之前被称为。在你的例子中,B1 ctor不能为C调用虚拟基础构造函数,因为稍后将调用B1 ctor本身。
答案 2 :(得分:1)
因为'B1'和'B2'对'C'使用相同的内存'C'。如果你没有在'C'中指定'A'的构造,那么'B1'或'B2'中的哪一个应该构造'A'?
这里的术语有点不对 - 这不是'A'的上传。
答案 3 :(得分:1)
因为您的class A
没有默认构造函数。
编译器为每个类生成一个默认构造函数,但是一旦你显式地重载了构造函数,它就会假定你想要做一些特殊的事情并且它不会生成默认构造函数,当你的代码试图调用默认构造函数时它会导致错误。
以下代码声明:
C () : B1(" this is " , " B1 ") , B2 (" this is " , " B2 ") {}
导致调用类A的默认构造函数,它根本不存在,因此导致错误。如果您为class A
提供 compile fine 的默认构造函数,而且没有任何错误。
答案 4 :(得分:1)
这是一个快速尝试:
#include <iostream>
class A { public: A(int v) : m_v(v) { std::cout << "Initializing A with " << v << std::endl; } int m_v; };
class B1 : public virtual A { public: B1(int v) : A(v) {} };
class B2 : public virtual A { public: B2(int v) : A(v) {} };
class C : public B1, public B2 { public: C(int v1, int v2, int v3) : A(v1), B1(v2), B2(v3) {} };
int main()
{
C c(1, 2, 3);
std::cout << "c.m_v: " << c.m_v << std::endl;
return EXIT_SUCCESS;
}
此示例输出:
Initializing A with 1
c.m_v: 1
也就是说,似乎在最派生类中需要调用A::A()
,因为继承是virtual
,它不会被B1
的构造函数调用或B2
实例化C
。