深入解析 C++ 中的成员对象与封闭类
成员对象与封闭类的基本概念
在 C++ 中,如果一个类包含其他类的对象作为其成员变量,则这些对象被称为成员对象,而该类则被称为封闭类。例如:
class Wheel {
public:
Wheel(int radius, int width) : m_radius(radius), m_width(width) {}
private:
int m_radius; // 轮胎半径
int m_width; // 轮胎宽度
};
class Engine {
public:
Engine() = default; // 默认构造函数
};
class Vehicle {
public:
Vehicle(int price, int wheelRadius, int wheelWidth)
: m_price(price), m_wheel(wheelRadius, wheelWidth) {}
private:
int m_price; // 车辆价格
Wheel m_wheel; // 成员对象:轮胎
Engine m_engine; // 成员对象:发动机
};
上述代码中,Vehicle 类是一个典型的封闭类,它包含两个成员对象:m_wheel 和 m_engine。
成员对象初始化的重要性
当创建一个封闭类对象时,必须确保所有成员对象都能正确初始化。例如,如果没有为 Vehicle 类定义构造函数,则编译器会尝试使用默认构造函数来初始化 m_wheel,但由于 Wheel 没有默认构造函数,因此会导致编译错误。
正确的做法是通过封闭类的构造函数初始化列表显式初始化成员对象:
Vehicle car(10000, 20, 50); // 初始化价格、轮胎半径和宽度
构造与析构顺序分析
封闭类的构造和析构过程遵循以下规则:
- 构造顺序:先执行所有成员对象的构造函数(按声明顺序),然后执行封闭类本身的构造函数。
- 析构顺序:先执行封闭类的析构函数,再依次销毁成员对象(逆序)。
示例代码如下:
#include <iostream>
class Wheel {
public:
Wheel() { std::cout << "Wheel 构造函数" << std::endl; }
~Wheel() { std::cout << "Wheel 析构函数" << std::endl; }
};
class Engine {
public:
Engine() { std::cout << "Engine 构造函数" << std::endl; }
~Engine() { std::cout << "Engine 析构函数" << std::endl; }
};
class Vehicle {
public:
Vehicle() { std::cout << "Vehicle 构造函数" << std::endl; }
~Vehicle() { std::cout << "Vehicle 析构函数" << std::endl; }
private:
Wheel m_wheel; // 第一步:构造成员对象 Wheel
Engine m_engine; // 第二步:构造成员对象 Engine
};
int main() {
Vehicle car;
return 0;
}
运行结果为:
Wheel 构造函数
Engine 构造函数
Vehicle 构造函数
Vehicle 析构函数
Engine 析构函数
Wheel 析构函数
复制构造函数的行为
当一个封闭类对象被复制时,其成员对象也会通过各自的复制构造函数进行复制。例如:
class Component {
public:
Component() { std::cout << "Component 构造函数" << std::endl; }
Component(const Component&) { std::cout << "Component 复制构造函数" << std::endl; }
};
class Container {
public:
Container() = default;
Container(const Container&) = default;
private:
Component m_component; // 成员对象
};
int main() {
Container c1; // 使用无参构造函数
Container c2(c1); // 使用复制构造函数
return 0;
}
输出结果为:
Component 构造函数
Component 复制构造函数
以上示例展示了如何在复制封闭类对象时触发成员对象的复制构造函数。