在C++中,构造函数本身并没有像普通成员函数那样的“修饰符”(如virtual
、static
等直接修饰函数本身的关键词),但有一些与构造函数相关的关键字或特性会影响其行为。这些特性可以看作是对构造函数的“修饰”或定义其作用的方式。以下是与C++构造函数相关的修饰符或特性及其作用:
1. 默认构造函数(Default Constructor)
-
形式:无参数的构造函数,或者所有参数都有默认值的构造函数。
-
作用:如果类中没有定义任何构造函数,编译器会自动生成一个默认构造函数,用于创建对象时初始化成员。如果程序员定义了其他构造函数但没有定义默认构造函数,则编译器不会生成默认的。
-
显式声明:可以用
= default
显式要求编译器生成默认构造函数,例如:class MyClass { public: MyClass() = default; // 显式声明默认构造函数 };
2. explicit 关键字
-
形式:在构造函数前加上
explicit
。 -
作用:防止构造函数被用于隐式类型转换。如果一个构造函数被标记为
explicit
,它只能用于显式构造对象,而不能在需要隐式转换时自动调用。例如:class MyClass { public: explicit MyClass(int x) {} }; MyClass obj = 5; // 错误:隐式转换被禁止 MyClass obj(5); // 正确:显式构造
-
用途:提高代码安全性,避免意外的类型转换。
3. delete 关键字
-
形式:在构造函数后加上
= delete
。 -
作用:禁用特定的构造函数,防止以某种方式创建对象。例如:
class MyClass { public: MyClass() = delete; // 禁用默认构造函数 MyClass(int x) {} }; MyClass obj; // 错误:默认构造函数被禁用
-
用途:限制对象的创建方式,例如强制要求参数化构造。
4. constexpr 关键字
-
形式:在构造函数前加上
constexpr
。 -
作用:表示该构造函数可以在编译期执行,用于生成常量表达式对象。要求构造函数体满足
constexpr
函数的需求(通常是简单初始化)。class MyClass { public: int value; constexpr MyClass(int v) : value(v) {} }; constexpr MyClass obj(10); // 编译期构造
-
用途:支持编译期计算,提升性能或用于静态断言。
5. 委托构造函数(Delegating Constructor)
-
形式:一个构造函数通过初始化列表调用同一类的另一个构造函数。
-
作用:减少代码重复,让一个构造函数“委托”给另一个构造函数执行初始化。
class MyClass { public: MyClass(int x) : value(x) {} MyClass() : MyClass(0) {} // 委托给带参数的构造函数 private: int value; };
-
用途:简化构造函数实现,避免冗余代码。
6. 初始化列表(Initializer List)
-
形式:在构造函数后使用冒号
:
接初始化列表。 -
作用:在构造函数体执行前初始化成员变量,尤其是
const
成员和引用成员(这些必须在初始化列表中初始化)。class MyClass { public: const int x; MyClass(int val) : x(val) {} };
-
用途:提高效率(避免二次赋值),处理无法通过赋值初始化的成员。
7. 继承中的构造函数(Inherited Constructor)
-
形式:使用
using Base::Base
从基类继承构造函数。 -
作用:允许派生类直接使用基类的构造函数,而无需显式定义。
class Base { public: Base(int x) {} }; class Derived : public Base { public: using Base::Base; // 继承基类的构造函数 }; Derived d(5); // 调用继承的构造函数
-
用途:简化派生类的代码,复用基类构造函数。
注意事项
- 没有
virtual
修饰:构造函数不能是虚函数,因为虚函数机制依赖于对象类型的动态绑定,而构造函数是在对象构造时调用的,此时虚表尚未建立。 - 没有
static
修饰:构造函数是为对象实例服务的,不能是静态函数。
总结
C++中的构造函数“修饰符”或特性包括explicit
(防止隐式转换)、= default
(要求默认实现)、= delete
(禁用构造函数)、constexpr
(编译期构造),以及委托构造和继承构造等机制。这些特性赋予构造函数灵活性和安全性,满足不同场景下的需求。