用C++解释空白类函数
Explain blank class functions in C++
class forums : public master{
public:
forums() : next(0),prev(0) {}
}
请解释一下 next(0( 和 prev(0( 函数到底是什么意思?
用逗号 (,( 分隔函数表示什么?这些函数旁边的空大括号 {} 有什么效果?
我是C++的初学者,并试图弄清楚这意味着什么,或者这些写作方式的预期用途?
比如它是专门为覆盖而设计的吗?
你有一个"初始化列表"。
该代码正在设置类实例的next
和prev
成员的初始值。
如果 next
和 prev
是类的实例,则该代码可能会调用构造函数,或者如果它们是基元类型,则可能只为它们赋值。
它们是逗号分隔的,因为这就是初始化列表的语法的外观。
空大括号表示 forums
构造函数的主体 - 在此示例中,构造函数本身没有任何变化,因为工作是在初始化列表中完成的。
1(它初始化下一个和上一个到0,就像初始化一样,而不是赋值。
2( 这称为构造函数初始值设定项列表。如果没有它,您需要在构造函数主体中将 next & prev 分配给 0。那不是一回事。您需要了解对象初始化和赋值之间的区别。对于某些类型、引用和 const 对象,初始值设定项列表是必需的。对于复杂对象,最好使用初始值设定项列表,因为在构造函数主体中分配对象时,您将为对象的初始化及其分配付费。对于简单的整型类型,没有区别,但对于具有构造函数的类型,有区别,因为通常,赋值几乎和初始化一样昂贵。
在这里,主体是空的,因为只有下一个和上一个需要初始化,不需要做任何其他事情。
此外,成员初始化顺序非常严格,它按照其声明的顺序发生。您在初始值设定项列表中写下的顺序无关紧要,它发生在声明顺序中。
非常重要,请了解初始化和分配之间的内容。
还要了解声明与定义。如果您不理解这些概念,就会产生很多困惑。
3(这是基本的对象构造。有一个空的身体,因为必须有一个身体;它什么都不做。
简答
这是一个具有空主体的构造函数,以及一个成员初始化列表,该列表将两个数据成员初始化为值 0
。
即
-
class-name([ ctor-args ]) [ : member-init-list ] { [ ctor-body ] }
-
member-init-list
在哪里member-name(args) [, member-name(args) [, ... ] ]
.
(注意:不是实际的C++词汇语法结构(
长答案
背景
采用以下类定义:
struct Base {};
struct Derived : Base {};
您可能已经意识到Derived
源自Base
。
您可能已经知道,Derived
和 Base
都有一个合成(隐式声明(默认(不带参数(构造函数。 Derived
的构造函数隐式/自动调用Base
。
现在让我们添加一个基本成员函数:
struct Derived : Base {
void foo() {}
};
我已经声明并定义了这个成员函数foo
;它的主体是空的,所以当你调用它时什么都不会发生。这是毫无意义的,但它是完全有效的。
现在,让我们创建自己的构造函数:
struct Derived : Base {
Derived() {}
};
这看起来更熟悉。它仍然是一个具有空体的 [特殊] 函数,并且 Base
构造函数仍在隐式调用。我们没有改变这一点。
处理数据成员
让我们添加一些数据成员并在构造函数中设置它们的值:
struct Derived : Base {
Derived() {
x = 0;
y = 0;
}
int x, y;
};
x
和y
都将具有对象构造后0
的值。这仍然是根本C++。
但您可能不知道的是,您没有初始化这些数据成员。您只是在可以初始化它们之后分配给它们。
事实上,内置类型的数据成员不是隐式初始化的,所以让我们选择一个更好的例子:
struct Derived : Base {
Derived() /* HERE */ {
x = "";
y = "";
}
std::string x, y;
};
x
和 y
在构造函数主体中的代码运行之前隐式初始化。当构造函数主体开始运行时,将初始化的所有成员都已初始化,并且已隐式调用基构造函数。
我们可以截获这种行为并提供我们自己的初始化值,方法是在我上一个代码片段中编写/* HERE */
的位置编写成员初始化器列表。使用成员初始化器列表,代码段如下所示:
struct Derived : Base {
Derived() : x(""), y("") {
x = "";
y = "";
}
std::string x, y;
};
哇!BKV现在我们将字符串初始化为 ""
,然后在构造函数主体中为它们分配相同的空值。我们可以摆脱这些任务,然后:
struct Derived : Base {
Derived() : x(""), y("") {}
std::string x, y;
};
现在构造函数主体是空的,但构造函数仍然执行操作。它隐式调用基构造函数,并显式初始化数据成员x
并y
为空字符串。
而且,由于std::string
有一个执行相同操作的默认构造函数,因此我们可以简短地编写:
struct Derived : Base {
Derived() : x(), y() {}
std::string x, y;
};
回到原始示例,这同样适用于内置类型的对象。让我们考虑两个要点:
struct Derived : Base {
Derived() : next(0), prev(0) {}
Derived* next;
Derived* prev;
};
处理基类
而且,作为额外的好处,我们可以使用成员初始化列表来显式调用基构造函数:
struct Derived : Base {
Derived() : Base(), next(0), prev(0) {}
Derived* next;
Derived* prev;
};
除非基构造函数想要一些参数,否则这是毫无意义的:
struct Base {
Base(int x) {}
};
struct Derived : Base {
Derived() : Base(0), next(0), prev(0) {}
Derived* next;
Derived* prev;
};
我希望这是有用的。
C++ 中的初始化列表
这不是一个函数。它具有与以下功能相同的功能:
forums()
{
next = 0;
prev = 0;
}
Next 和 Prev 可能是基类的成员。
但是存在差异 - 首先,使用初始化列表比事后为成员分配值更快。
- 如何通过派生类函数更改基类中的向量
- 库函数需要一个 std::function<void(void)>,如何传入类函数?
- 在类函数中初始化外部作用域变量
- c++ 在非类函数中使用类变量
- SDL_PollEvent() 无法捕获类函数内部SDL_QUIT?
- 从类成员函数到类 C 函数指针的转换
- 如何在模板类函数中分配结构值?
- 有没有办法将重载的类函数绑定到函数对象?
- 启动类函数作为失去引用的线程
- C++调用使用重写函数的父类函数
- 将值传递到另一个类函数在打印时为零
- 计算对类函数的所有调用次数
- 由于签名差异,调用了错误的子类函数
- 使用宏调用类函数
- 虚拟基类函数中派生类的大小
- 模板类/函数中的交叉前向声明
- 在C++中使用非静态类函数的函数
- 无法访问基类函数 C++
- 类函数返回到另一个类函数返回打印不同的值
- 用C++解释空白类函数