类与对象

翻译整理自 cppreference - 类。

1. 定义类

class Point {
public:
    Point(int x, int y) : x_(x), y_(y) {}     // 构造函数
    int x() const { return x_; }
    int y() const { return y_; }

private:
    int x_, y_;
};

Point p(1, 2);
std::cout << p.x();

struct 默认公开成员,class 默认私有,其他完全一致。

2. 构造函数

class Foo {
public:
    Foo() = default;                          // 默认构造
    Foo(int x) : x_(x) {}                     // 普通构造
    Foo(const Foo&) = delete;                 // 禁止拷贝
    Foo(Foo&&) noexcept = default;             // 默认移动

    Foo(int x, int y) : x_(x), y_(y) {}       // 多参数

private:
    int x_ = 0, y_ = 0;
};

委托构造(C++11)

class Foo {
public:
    Foo() : Foo(0) {}
    Foo(int x) : x_(x) {}
private:
    int x_;
};

explicit 防隐式转换

class String {
public:
    explicit String(const char* s);
};

String s1 = "x";   // ❌ explicit 禁止
String s2("x");    // OK

3. 析构函数

class Buffer {
public:
    Buffer(size_t n) : data_(new char[n]) {}
    ~Buffer() { delete[] data_; }            // 释放
private:
    char* data_;
};

如果类管理资源,应遵循三/五法则:

  • 三:定义析构 + 拷贝构造 + 拷贝赋值
  • 五(C++11):加上移动构造 + 移动赋值

或更推荐零法则:使用 RAII 容器(如 std::vector、std::unique_ptr),让编译器自动生成。

4. 拷贝与移动

class V {
public:
    V() = default;
    V(const V&) = default;                   // 拷贝构造
    V& operator=(const V&) = default;         // 拷贝赋值
    V(V&&) noexcept = default;                // 移动构造
    V& operator=(V&&) noexcept = default;    // 移动赋值
};

V a;
V b = a;              // 拷贝
V c = std::move(a);   // 移动

5. 访问控制

  • public:公开
  • private:私有(仅本类与友元)
  • protected:派生类可访问
class A {
public:    int x;
protected: int y;
private:   int z;
};

friend 友元

class Account {
    friend class Bank;
private:
    int balance;
};

class Bank {
    void view(Account& a) { std::cout << a.balance; }
};

6. 静态成员

class Counter {
public:
    static int count;
    Counter() { ++count; }
};
int Counter::count = 0;                       // 定义

C++17 起 inline static 可就地初始化:

class Counter {
    inline static int count = 0;
};

7. this 指针

class Builder {
public:
    Builder& setName(const std::string& n) {
        name_ = n;
        return *this;                        // 链式调用
    }
private:
    std::string name_;
};

Builder b;
b.setName("a");

8. const 成员函数

class Vec {
public:
    int size() const { return size_; }        // const,不修改对象
};

const 对象只能调用 const 成员函数。

9. mutable

允许 const 函数中修改:

class Cache {
public:
    int compute() const {
        if (cached_) return value_;
        value_ = expensive();
        cached_ = true;
        return value_;
    }
private:
    mutable bool cached_ = false;
    mutable int   value_  = 0;
};

10. 运算符重载

class Vec2 {
public:
    Vec2(int x, int y) : x_(x), y_(y) {}
    Vec2 operator+(const Vec2& r) const {
        return Vec2{x_ + r.x_, y_ + r.y_};
    }
    int operator[](size_t i) const {
        return i == 0 ? x_ : y_;
    }
    friend std::ostream& operator<<(std::ostream& os, const Vec2& v) {
        return os << "(" << v.x_ << "," << v.y_ << ")";
    }
private:
    int x_, y_;
};

Vec2 a{1, 2}, b{3, 4};
std::cout << (a + b);

11. 用户定义字面量(C++11)

constexpr long double operator""_deg(long double d) {
    return d * 3.14159 / 180.0;
}

auto r = 90.0_deg;

12. 类型转换运算符

class FilePath {
public:
    operator std::string() const { return path_; }
private:
    std::string path_;
};

std::string p = FilePath();

显式转换避免误用:

explicit operator std::string() const;

小结

C++ 类支持构造、析构、拷贝、移动、运算符重载、模板等,让用户类型像内置类型一样自然。