在构造函数中必须用初始化列表的情况

本文详细解析了C++中构造函数的使用方法,包括初始化列表的用途、成员变量的初始化方式,以及何时应该使用初始化列表而非直接赋值。特别强调了对于引用成员和const成员变量的初始化要求。
1:初始化列表”来初始化成员变量,是进行初始化工作,调用的是构造函数,

只需要调用一次拷贝构造函数!

2:在构造函数里面直接赋值,是进行的赋值操作,调用的是assignment函数

再调用assignment函数之前,还必要调用一次默认构造函数!

3:有些时候必须用到初始化列表,而不能在构造函数里直接赋值,比如引用成员

和const成员,因为它们都不能被赋值,而只可以被初始化!


4除了const和引用成员之外,没有提供默认构造函数的类对象,也都需要在初始化列表来完成初始化。
### C++ 类防止派生但允许外部创建多个实例的实现方式 在 C++ 中,可以通过将类声明为 `final` 来禁止派生,同时通过将构造函数设为公有(`public`)来允许外部创建多个实例。以下是具体实现方法: #### 禁止派生 C++11 引入了 `final` 关键字,用于指定一个类不能被继承。如果尝试从标记为 `final` 的类派生新类,编译器将报错[^2]。 ```cpp class Base final { // 使用 final 关键字禁止派生 public: Base() { std::cout << "Base constructor" << std::endl; } }; ``` 尝试派生时会引发编译错误: ```cpp class Derived : public Base { }; // 编译错误:cannot derive from 'final' type 'Base' ``` #### 允许多个实例 为了允许外部创建该类的多个实例,需确保构造函数为公有(`public`)。这样,任何外部代码都可以通过调用构造函数创建该类的对象[^2]。 ```cpp class NonDerivable final { // 禁止派生 public: NonDerivable() { std::cout << "NonDerivable instance created" << std::endl; } void display() const { std::cout << "This is a NonDerivable object" << std::endl; } }; int main() { NonDerivable obj1; // 创建第一个实例 obj1.display(); NonDerivable obj2; // 创建第二个实例 obj2.display(); return 0; } ``` --- ### 自定义构造函数必须使用初始化列表情况 在某些情况下,自定义构造函数必须使用初始化列表,而不是在构造函数体内进行赋值操作。以下是几种必要场景及其原因: #### 1. 常量成员变量 如果类中包含常量成员变量(`const`),则必须在初始化列表中对其进行初始化,因为常量成员变量一旦声明后就不能再修改[^1]。 ```cpp class Foo { private: const int a; public: Foo(int value) : a(value) {} // 必须使用初始化列表 }; ``` #### 2. 引用成员变量 引用成员变量必须在初始化列表初始化,因为它不能在构造函数体内赋值[^1]。 ```cpp class Bar { private: int& ref; public: Bar(int& value) : ref(value) {} // 必须使用初始化列表 }; ``` #### 3. 没有默认构造函数的成员 如果类中的某个成员没有默认构造函数,则必须在初始化列表中显式初始化它[^1]。 ```cpp class Member { public: Member(int x) : value(x) {} private: int value; }; class Container { private: Member member; public: Container(int x) : member(x) {} // 必须使用初始化列表 }; ``` #### 4. 提高效率 即使成员变量可以使用默认构造函数,但如果直接在初始化列表初始化,可以避免不必要的默认构造和后续赋值操作,从而提高效率。 ```cpp class Example { private: int a; int b; public: Example(int x, int y) : a(x), b(y) {} // 高效的初始化 }; ``` #### 初始化顺序与声明顺序一致 无论初始化列表中的顺序如何,成员变量的初始化顺序始终与其在类中声明的顺序一致。因此,建议初始化列表的顺序与声明顺序保持一致,以避免潜在问题。 ```cpp class Foo { private: int a; int b; public: Foo(int x, int y) : b(y), a(x) {} // 实际初始化顺序是 a -> b }; ``` --- ### 总结 - 禁止派生但允许外部创建多个实例可以通过将类声明为 `final` 并将构造函数设为公有来实现。 - 自定义构造函数必须使用初始化列表的场景包括:常量成员变量、引用成员变量、没有默认构造函数的成员以及为了提高效率。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值