ELL*_*BLE 4 c++ inheritance constructor class multiple-inheritance
(如果之前有人询问过,我很抱歉;搜索功能似乎已被破坏:结果区域完全是空白的,即使它表示在Chrome,FireFox和Safari中有几页结果...
所以,我只是在学习C++ ......而我正在阅读的这本书在解释构造函数方面做得非常糟糕,我能够掌握它们.到目前为止,我已经非常了解其他所有内容,但我无法弄清楚构造函数的语法实际上是如何工作的.
例如,我被告知以下将导致构造函数调用指定的超类的构造函数:
class something : something_else {
something(int foo, double bar) : something_else(int foo) {}
};
Run Code Online (Sandbox Code Playgroud)
另一方面,在描述如何初始化const成员时,本书后面使用了相同的语法:
class something : something_else {
private: const int constant_member;
public: something(int foo, double bar) : constant_member(42) {}
};
Run Code Online (Sandbox Code Playgroud)
那么......呃......那到底是怎么回事?语法rv signature(param) : something_else(what);究竟意味着什么?我无法弄清楚它something_else(what)是什么,与周围的代码有关.它似乎具有多重含义; 我确信必须有一些它所对应的语言的基本元素,我只是无法弄清楚是什么.
编辑:另外,我应该提一下,what前面的例子中有时候是一个参数列表(所以something_else(what)看起来像一个函数签名)是非常令人困惑的......有时候是一个常量值表达式(所以something_else(what)看起来像一个函数调用).
现在,继续:多继承和构造函数怎么样?如何指定调用父类的构造函数以及默认调用哪些构造函数?我知道,默认情况下,以下两个是相同的......但是我不确定涉及多重继承时的等价物是什么:
class something : something_else {
//something(int foo, double bar) : something_else() {}
something(int foo, double bar) {}
};
Run Code Online (Sandbox Code Playgroud)
任何帮助解决这些主题的人都会非常感激; 我不喜欢这种感觉,我没有理解基本的东西.我不喜欢它在所有.
编辑2:好的,截至目前的答案都非常有用.他们提出了这个问题的另一部分:"初始化列表"中的基类构造函数调用的参数如何与您定义的构造函数相关?他们必须匹配......是否必须有默认值?他们有多少匹配?换句话说,以下哪项是非法的:
class something_else {
something_else(int foo, double bar = 0.0) {}
something_else(double gaz) {}
};
class something : something_else {
something(int foo, double bar) : something_else(int foo, double bar) {} };
class something : something_else {
something(int foo) : something_else(int foo, double bar) {} };
class something : something_else {
something(double bar, int foo) : something_else(double gaz) {} };
Run Code Online (Sandbox Code Playgroud)
构造函数定义的语法是:
Type( parameter-list ) : initialization-list
{
constructor-body
};
Run Code Online (Sandbox Code Playgroud)
其中'initialization-list'是以逗号分隔的对base和/或成员属性的构造函数的调用列表.需要初始化没有默认构造函数,常量子对象和引用属性的任何子对象(基础或成员),并且在所有其他情况下应优先于构造函数块中的赋值.
struct base {
base( int ) {};
};
struct base2 {
base2( int ) {};
};
struct type : base, base2
{
type( int x )
: member2(x),
base2(5),
base(1),
member1(x*2)
{ f(); }
int member1;
int member2;
};
Run Code Online (Sandbox Code Playgroud)
执行初始化列表的顺序在类声明中定义:基于它们的声明顺序,成员属性按声明的顺序排列.在上面的示例中,在f()构造函数体中执行之前,类将按以下顺序初始化其基类和属性:
base(int)使用参数1 调用构造函数base2(int)使用参数5 调用构造函数member1用值初始化x*2member2用值初始化x当您引入虚拟继承时,虚拟基础在虚拟继承层次结构的最派生类中初始化,因此它可以(或必须,如果没有默认构造函数)出现在该初始化列表中.在这种情况下,虚拟基础将在第一个子对象之前初始化,该子对象实际上从该基础继承.
class unrelated {};
class base {};
class vd1 : virtual base {};
class vd2 : virtual base {};
struct derived : unrelated, vd1, vd2 {
derived() : unrelated(), base(), vd1(), vd2() {} // in actual order
};
Run Code Online (Sandbox Code Playgroud)
在编辑2
我想你不是在阅读答案中的细节.初始化列表中的元素是构造函数调用,而不是声明.如果合适,编译器将应用通常的转换规则.
struct base {
base( int x, double y );
explicit base( char x );
};
struct derived : base {
derived() : base( 5, 1.3 ) {}
derived( int x ) : base( x, x ) {}
// will convert x into a double and call base(int,double)
derived( double d ) : base( 5 ) {}
// will convert 5 to char and call base(char)
// derived( base b ) {} // error, base has no default constructor
// derived( base b, int x ) : base( "Hi" ) {}
// error, no constructor of base takes a const char *
};
Run Code Online (Sandbox Code Playgroud)