在C++中的多重继承中调用构造函数中的基成员
Calling a base member in constructor in multiple inheritance in C++
假设我有这两个类
class base_size
{
public:
int size()
{ return 5; }
};
class base_implement
{
public:
base_implement(int s) : _vec(s)
{
cout << "size : " << _vec.size() << endl;
}
private:
vector<float> _vec;
};
如果我从这两个类中继承,那么在另一个类的构造函数中调用其中一个类成员函数可以吗?例如
class derived :
public base_implement,
public base_size
{
public:
derived() : base_size(), base_implement(size())
{
// Is this OK?
// If derived is not yet constructed can I access this->size() ?
// Works in VC++. Not sure about other compilers.
}
};
原则上没关系。基子对象和成员对象是在派生构造函数体运行之前构造的,因此可以毫无问题地调用成员函数。您甚至可以在构造函数中调用自己的成员函数;您只需要确保它们不依赖于稍后在同一构造函数中出现的任何内容。
只需确保按正确的顺序(即其声明的顺序)调用基初始值设定项,和/或修复类定义:对于base_size::size()
,您希望base_size
子对象是完全构造的,因此它必须放在第一位。
class derived : base_size, base_implement
{
derived() : base_size(), base_implement(size()) { /* ... */ }
// ...
};
您可以安全地从初始化列表中调用继承的成员函数,前提是该函数的作用不取决于该继承级别的成员数据是如何初始化的。而且,由于size()
不依赖于任何成员数据,它所做的只是返回一个文本
int size()
{ return 5; }
您的代码可以与任何编译器配合使用。因此,在初始化列表中甚至不需要base_size()
derived() : base_size(), base_implement(size())
在这种情况下。
然而,切换到一个更现实的例子,其中base_size
有一个初始化实例变量(即成员数据)的构造函数,在初始化列表中有base_size()
会更有意义:
class base_size
{
public:
base_size ()
{ _size = 5; } // initialization
int size()
{ return _size; }
private:
int _size; // instance variable
};
class base_implement
{
public:
base_implement(int s) : _vec(s)
{
cout << "size : " << _vec.size() << endl;
}
private:
vector<float> _vec;
};
class derived :
public base_implement,
public base_size
{
public:
derived() : base_size(), base_implement(size())
{
// crash
}
};
而且,在这个特定的例子中,程序会崩溃,因为vector
不会接收到分配其大小的有效值。原因可能是在所谓的基说明符列表:中基类的顺序
public base_implement,
public base_size
关于权威机构,这是标准在第12.6.2节中所规定的,";初始化基和成员";
初始化应按以下顺序进行:
- 首先,仅对于下面描述的最派生类的构造函数,虚拟基类应按照它们在基类的有向无环图的深度优先从左到右遍历中出现的顺序进行初始化,其中"从左到左"是派生类基类说明符列表中基类名称的出现顺序
- 然后,直接基类应按照它们出现在基说明符列表中的声明顺序进行初始化(无论mem初始化器的顺序如何)
- 然后,非静态数据成员应按照它们在类定义中声明的顺序进行初始化(同样,与mem初始化程序的顺序无关)
- 最后,构造函数的主体被执行
所以如果你要更换
public base_implement,
public base_size
带有
public base_size,
public base_implement
这一切都将正确初始化,程序将在大多数符合标准的编译器中运行良好。首先,我刚刚测试过MSVC 10.0。
相关文章:
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 继承:构造函数,初始化C++11中基类的类C数组成员
- C++-我可以创建另一个类的成员并在构造函数中使用它吗
- 如果基类包含双指针成员,则派生类的构造函数
- 为什么类中的ostringstream类型的成员会导致";调用隐含删除复制构造函数";错误
- constexpr构造函数需要常量成员函数时出现问题
- 如何在c++中定义以struct为数据成员的类中的构造函数
- 在作为静态成员包含在另一个类中的类的构造函数中使用 cout
- std::ofstream 作为类成员删除复制构造函数?
- c++构造函数成员初始化:传递参数
- C++初始化类实例时隐式调用类成员的构造函数
- 基类中的默认析构函数禁用子类中的移动构造函数(如果有成员)
- 在构造函数中输入对象时C++类成员作用域
- 解释了构造函数成员初始化列表
- 构造函数成员初始值设定项跨成员列出,安全吗?
- C 构造函数成员分配优化
- 类内/构造函数成员初始化
- 在构造函数成员初始化之前调用成员函数的语法
- 非构造函数成员函数中的显式字符串行为