gpt4 book ai didi

c++ - C++ 中是否有两种类型的成员初始值设定项列表?

转载 作者:行者123 更新时间:2023-11-28 00:42:13 25 4
gpt4 key购买 nike

我看到了两种使用成员初始化列表的不同方式。第一个是这样的:

class ClassName {
public:
arg_type_1 varName1;
arg_type_2 varName2;

// Constructor.
ClassName(arg_type_1 arg_name_1, arg_type_2 arg_name_2)
: varName1(arg_name_1), varName2(arg_name_2)
{
}
}

那里发生的事情很清楚。在构造函数中,我们有一个参数列表,我们使用它们来初始化类的成员。例如arg_name_1用于初始化 varName1 的值类的变量。

另一种使用成员初始化器的方式出现在继承的情况下:

class ChildClass : public ParentClass
{
ChildClass(string name) : ParentClass( name )
{
// What can we put here and why we might need it.
}
};

这里发生的事情也很清楚。当我们调用 ChildClass 的构造函数时使用一个字符串参数,它调用 ParentClass 的构造函数使用相同的字符串参数。

我不清楚的是编译器如何区分这两种情况(语法相同)。例如,在第二个示例中,编译器可能认为它需要获取 name 的值。变量并将其分配给 ParentClass ChildClass 的变量然后它看到这样一个变量没有在 ChildClass 中声明.

我不明白的第二点是为什么我们可能想把一些内容放在第二个例子的构造函数的主体中。即使没有任何东西,它也已经使用父类的构造函数创建并返回一个对象。

最佳答案

What is not clear to me, is how compiler distinguish these two cases (the syntax is the same).

看到列表中的初始化器,编译器首先查找具有该名称的成员变量。如果找到一个,它会尝试用给定的参数初始化该成员。如果没有,它会查找具有该名称的直接基类或虚拟基类,以使用给定参数初始化基类子对象。这些是在类的方法(包括构造函数)中命名某些内容时应用的常用名称查找规则。

在罕见且设计糟糕的情况下,当您同时拥有同名的成员变量和直接基类时,您将必须限定基类类型,即添加命名空间:

struct B1 {
B1(char const*) {};
};
namespace Foo {
struct B2 {
B2(bool) {};
};
}

struct Weird : public B1, public Foo::B2 {
int B1;
double B2;

Weird()
: ::B1("meow")
, Foo::B2(false)
, B1(42)
, B2(3.14)
{}
};

The second unclear point to me is why we might want to put some content in the body of the constructor from the second example. Even of there is nothing it already creates and returns an object using the constructor of the parent class.

它实际上并没有返回任何对象,它只是创建了那个对象。但是,有人可能想像这样调用其他函数:

class ParentClass {
public:
ParentClass(string name);
void registerSomething(ParentClass const&);
}

class ChildClass : public ParentClass {
public:
ChildClass(string name) : ParentClass( name ) {
registerSomething(*this);
}
};

有人想要这样做的原因可能有很多。一般来说,由于子类比父类“多”一些,所以如果它想在其构造函数中做更多的事情而不仅仅是初始化基类子对象,那是很自然的。

关于对象生命周期的一些话:在进入构造函数体之前,你只构造了新对象的子对象。当执行离开构造函数主体时,对象本身开始其生命周期。打个比方,汽车及其零件:在进入汽车的构造体之前,您已经给轮胎充气、组装发动机并冲压出车身部件。但是你的车如果没有组装就不是汽车,这发生在构造函数的主体中。这反射(reflect)在析构函数中,尤其是在存在异常时可以看到:如果在对象的构造函数期间发生异常,则不会调用其析构函数。只会调用已经完全构建的子对象的析构函数。这是因为如果构造函数没有完成执行,对象就不会存在,也没有什么可以调用析构函数。

关于c++ - C++ 中是否有两种类型的成员初始值设定项列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18248794/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com