Sim*_*yOm 15 c++ inheritance multiple-inheritance virtual-inheritance c++11
现在,我正在学习C++中的继承功能,并希望测试最近学到的虚拟基类的概念.我尝试了以下简单的代码:
#include <iostream>
using namespace std;
class A
{
private:
int m_value;
string m_caller;
public:
A(int p_value, string p_caller) : m_value{p_value}, m_caller{p_caller}
{
cout<<"Instantiating A via "<<m_caller<<endl;
}
};
class B : virtual public A
{
private:
int m_value;
public:
B(int p_value1,int p_value2) : A{p_value1,"B"}, m_value{p_value2}
{
cout<<"Instantiating B."<<endl;
}
};
class C : public B
{
public:
C(int p_value1,int p_value2) : A{p_value1,"C"}, B(p_value1, p_value2)
{
cout<<"Instantiating C."<<endl;
}
};
int main()
{
C c1(1,2);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
请注意B(p_value1, p_value2)在C类的构造函数中.这给了我想要的输出:
Instantiating A via C
Instantiating B.
Instantiating C.
Run Code Online (Sandbox Code Playgroud)
但是,在我改变它的那一刻B{p_value1, p_value2},我得到了以下输出:
Instantiating A via C
Instantiating A via B
Instantiating B.
Instantiating C.
Run Code Online (Sandbox Code Playgroud)
我试着寻找答案,但我得到的所有答案都引用了一些C++标准.作为OOP的初学者,我正在寻找一个更简单的解释这种行为.非常感谢!
PS我在Windows中使用C :: B编译器g ++ 4.8.1.
这是g ++中的编译器错误.
在C++ 14(N4140)部分[dcl.init.list]中,列表初始化的定义是(为简洁而编辑):
对象或类型引用的列表初始化
T定义如下:
- 如果
T是聚合,则执行聚合初始化- 否则,如果初始化列表没有元素并且
T是具有默认构造函数的类类型,则对象将进行值初始化.- 否则,如果
T是std :: initializer_list的特化,[...]- 否则,如果
T是类类型,则考虑构造函数.枚举适用的构造函数,并通过重载解析选择最佳构造函数.如果转换任何参数需要缩小转换,则程序格式不正确.- [...]
前3个点不适用:B不是聚合(聚合不能有基类),初始化列表确实有元素,B不是专门化的std::initializer_list.
第四点确实适用,因为重载决议符合[over.match.list] /1.2 B{p_value1, p_value2}的构造B(int, int)函数:
如果找不到可行的初始化列表构造函数,则再次执行重载解析,其中候选函数是类的所有构造函数,
T参数列表由初始化列表的元素组成.
它从最后一个引用开始,B(whatever)并且B{whatever}应该表现相同.
| 归档时间: |
|
| 查看次数: |
294 次 |
| 最近记录: |