class DemoDelegating final // final 防止类被继承
{
private:
int a; // 成员变量
public:
DemoDelegating(int x) : a(x) // 基本的构造函数
{}
DemoDelegating() : // 无参数的构造函数
DemoDelegating(0) // 给出默认值,委托给第一个构造函数
{}
DemoDelegating(const string& s) : // 字符串参数构造函数
DemoDelegating(stoi(s)) // 转换成整数,再委托给第一个构造函数
{}
};
class DemoInit final // 有很多成员变量的类
{
private:
int a = 0; // 整数成员,赋值初始化
string s = "hello"; // 字符串成员,赋值初始化
vector<int> v{1, 2, 3}; // 容器成员,使用花括号的初始化列表
public:
DemoInit() = default; // 默认构造函数
~DemoInit() = default; // 默认析构函数
public:
DemoInit(int x) : a(x) {} // 可以单独初始化成员,其他用默认值
};
using uint_t = unsigned int; // using 别名
typedef unsigned int uint_t; // 等价于 using
C++ 支持将对象存储在栈上面。但是,在很多情况下,对象不能、或不应该,存储在栈上。比如:
所以可以利用栈展开的时候,在栈变量析构函数中释放内存。
在析构函数里做必要的清理工作,这就是 RAII 的基本用法。这种清理并不限于释放内存,也可以是:
以下是一个工厂方法的案例,保证了返回对象能够有序的释放对象内存
#include <iostream>
using namespace std;
enum class ShapeType {
circle,
triangle,
rectangle,
};
class Shape {};
class Circle : public Shape {};
class Triangle: public Shape {};
class Rectangle: public Shape {};
class ShapeWrapper {
public:
explicit ShapeWrapper(Shape* ptr = nullptr) : ptr_(ptr) {} // explicit 避免隐式转换
~ShapeWrapper() {
cout << "~ShapeWrapper" << endl;
delete ptr_; // 释放空指针会做判断,所以不会出错
} // 保证在析构的时候释放 ptr_
Shape* get() const { return ptr_; }
private:
Shape* ptr_;
};
Shape* create_shape(ShapeType type) {
switch (type) {
case ShapeType::circle:
return new Circle;
case ShapeType::triangle:
return new Triangle;
case ShapeType::rectangle:
return new Rectangle;
}
return nullptr;
}
void check_raii() {
// 这里将 create_shape 返回的指针放到 Wrapper 中
// 编译器会自动调用析构函数,包括在函数执行发生异常的情况。(栈展开)
// 在函数退出时,对 栈变量 ptr 执行析构,释放 create_shape 申请的堆上的内存
ShapeWrapper ptr(create_shape(ShapeType::circle));
}