调用超类构造函数的规则是什么?
从子类调用超类构造函数的C ++规则是什么?
例如,我知道在Java中,您必须将其作为子类构造函数的第一行(如果您不这样做,则假定隐式调用no-arg超级构造函数 - 如果缺少它,会给您一个编译错误) 。
如果没有参数,基类构造函数会自动调用。 如果要使用参数调用超类构造函数,则必须使用子类的构造函数初始化列表。 与Java不同,C ++支持多重继承(无论好坏),所以基类必须按名称引用,而不是“super()”。
class SuperClass
{
public:
SuperClass(int foo)
{
// do something with foo
}
};
class SubClass : public SuperClass
{
public:
SubClass(int foo, int bar)
: SuperClass(foo) // Call the superclass constructor in the subclass' initialization list.
{
// do something with bar
}
};
关于这里和这里的构造函数初始化列表的更多信息。
在C ++中,所有超类和成员变量的无参构造函数都会在进入构造函数之前调用。 如果你想传递它们的参数,这个叫做“构造函数链接”的单独语法如下所示:
class Sub : public Base
{
Sub(int x, int y)
: Base(x), member(y)
{
}
Type member;
};
如果此时运行的任何内容抛出,先前完成构建的基础/成员将调用它的析构函数,并将异常重新抛出给调用者。 如果要在链接期间捕获异常,则必须使用函数try块:
class Sub : public Base
{
Sub(int x, int y)
try : Base(x), member(y)
{
// function body goes here
} catch(const ExceptionType &e) {
throw kaboom();
}
Type member;
};
在这种形式下,请注意try块是函数的主体,而不是在函数体内; 这允许它捕获由隐式或显式成员和基类初始化引发的异常,以及在函数的主体期间。 但是,如果函数catch块不会引发其他异常,则运行时将重新抛出原始错误; 初始化期间的异常不能被忽略。
在C ++中,有一个构造函数初始化列表的概念,您可以并且应该调用基类的构造函数,并且还应该初始化数据成员。 初始化列表出现在冒号后面的构造函数签名之后,并且位于构造函数的主体之前。 假设我们有一个A类:
class A : public B
{
public:
A(int a, int b, int c);
private:
int b_, c_;
};
然后,假设B有一个接受int的构造函数,A的构造函数可能如下所示:
A::A(int a, int b, int c)
: B(a), b_(b), c_(c) // initialization list
{
// do something
}
如您所见,基类的构造函数在初始化列表中调用。 顺便说一句,初始化初始化列表中的数据成员优于为构造函数的body中的b_和c_赋值,因为这样可以节省额外的赋值成本。
请记住,数据成员总是按照它们在类定义中声明的顺序进行初始化,而不管它们在初始化列表中的顺序如何。 为了避免在数据成员彼此依赖时可能出现的奇怪错误,您应该始终确保成员顺序在初始化列表和类定义中相同。 基于同样的原因,基类构造函数必须是初始化列表中的第一项。 如果完全忽略它,那么将自动调用基类的默认构造函数。 在这种情况下,如果基类没有默认构造函数,那么将会出现编译器错误。
链接地址: http://www.djcxy.com/p/18009.html上一篇: What are the rules for calling the superclass constructor?