Skip to content

C++ 类和对象

概述

类和对象是面向对象编程的核心概念。类是对象的蓝图或模板,定义了对象的属性(数据成员)和行为(成员函数)。对象是类的实例,是具体存在的实体。C++作为面向对象编程语言,提供了强大的类机制来组织和管理代码。

🏗️ 类的基本概念

类的定义和声明

cpp
#include <iostream>
#include <string>

// 基本类定义
class Student {
private:
    std::string name_;
    int age_;
    double gpa_;
    
public:
    // 构造函数
    Student(const std::string& name, int age, double gpa) 
        : name_(name), age_(age), gpa_(gpa) {}
    
    // 成员函数
    void displayInfo() const {
        std::cout << "姓名: " << name_ << ", 年龄: " << age_ 
                  << ", GPA: " << gpa_ << std::endl;
    }
    
    // 访问器(getter)
    std::string getName() const { return name_; }
    int getAge() const { return age_; }
    double getGPA() const { return gpa_; }
    
    // 修改器(setter)
    void setAge(int age) { 
        if (age > 0) age_ = age; 
    }
    
    void setGPA(double gpa) { 
        if (gpa >= 0.0 && gpa <= 4.0) gpa_ = gpa; 
    }
};

int main() {
    std::cout << "=== 类和对象基础 ===" << std::endl;
    
    // 创建对象
    Student student1("张三", 20, 3.5);
    Student student2("李四", 19, 3.8);
    
    // 使用对象
    student1.displayInfo();
    student2.displayInfo();
    
    // 修改对象状态
    student1.setAge(21);
    student1.setGPA(3.7);
    
    std::cout << "\n修改后:" << std::endl;
    student1.displayInfo();
    
    return 0;
}

构造函数和析构函数

cpp
#include <iostream>
#include <string>

class Resource {
private:
    std::string name_;
    int* data_;
    size_t size_;
    
public:
    // 默认构造函数
    Resource() : name_("Default"), data_(nullptr), size_(0) {
        std::cout << "默认构造函数: " << name_ << std::endl;
    }
    
    // 参数化构造函数
    Resource(const std::string& name, size_t size) 
        : name_(name), size_(size) {
        data_ = new int[size_];
        for (size_t i = 0; i < size_; i++) {
            data_[i] = static_cast<int>(i);
        }
        std::cout << "参数化构造函数: " << name_ << std::endl;
    }
    
    // 拷贝构造函数
    Resource(const Resource& other) 
        : name_(other.name_), size_(other.size_) {
        data_ = new int[size_];
        for (size_t i = 0; i < size_; i++) {
            data_[i] = other.data_[i];
        }
        std::cout << "拷贝构造函数: " << name_ << std::endl;
    }
    
    // 析构函数
    ~Resource() {
        delete[] data_;
        std::cout << "析构函数: " << name_ << std::endl;
    }
    
    void display() const {
        std::cout << "资源 " << name_ << " (大小: " << size_ << "): ";
        for (size_t i = 0; i < size_; i++) {
            std::cout << data_[i] << " ";
        }
        std::cout << std::endl;
    }
    
    std::string getName() const { return name_; }
};

int main() {
    std::cout << "=== 构造函数和析构函数 ===" << std::endl;
    
    {
        Resource r1;                              // 默认构造
        Resource r2("Resource2", 5);              // 参数化构造
        Resource r3 = r2;                         // 拷贝构造
        
        r2.display();
        r3.display();
        
        std::cout << "作用域结束前..." << std::endl;
    }  // 作用域结束,自动调用析构函数
    
    std::cout << "作用域结束后" << std::endl;
    
    return 0;
}

🔒 访问控制

public、private、protected

cpp
#include <iostream>

class AccessExample {
private:
    int private_data_;        // 只能在类内部访问
    
protected:
    int protected_data_;      // 类内部和派生类可访问
    
public:
    int public_data_;         // 任何地方都可访问
    
public:
    AccessExample(int priv, int prot, int pub) 
        : private_data_(priv), protected_data_(prot), public_data_(pub) {}
    
    // 公有接口访问私有数据
    int getPrivateData() const { return private_data_; }
    void setPrivateData(int value) { private_data_ = value; }
    
    void showAllData() const {
        std::cout << "私有: " << private_data_ 
                  << ", 保护: " << protected_data_ 
                  << ", 公有: " << public_data_ << std::endl;
    }
    
protected:
    void protectedMethod() {
        std::cout << "保护方法被调用" << std::endl;
    }
    
private:
    void privateMethod() {
        std::cout << "私有方法被调用" << std::endl;
    }
};

// 派生类演示protected访问
class DerivedAccess : public AccessExample {
public:
    DerivedAccess(int priv, int prot, int pub) 
        : AccessExample(priv, prot, pub) {}
    
    void demonstrateAccess() {
        // protected_data_ = 100;  // OK: 可以访问protected成员
        public_data_ = 200;        // OK: 可以访问public成员
        // private_data_ = 300;    // 错误!不能访问private成员
        
        protectedMethod();         // OK: 可以调用protected方法
        // privateMethod();        // 错误!不能调用private方法
    }
};

int main() {
    std::cout << "=== 访问控制 ===" << std::endl;
    
    AccessExample obj(10, 20, 30);
    
    // 外部访问
    std::cout << "公有数据: " << obj.public_data_ << std::endl;
    // std::cout << obj.private_data_;    // 错误!外部不能访问private
    // std::cout << obj.protected_data_;  // 错误!外部不能访问protected
    
    // 通过公有接口访问私有数据
    std::cout << "私有数据(通过getter): " << obj.getPrivateData() << std::endl;
    
    obj.setPrivateData(100);
    obj.showAllData();
    
    // 派生类访问演示
    DerivedAccess derived(1, 2, 3);
    derived.demonstrateAccess();
    
    return 0;
}

🏛️ 静态成员

静态数据成员和静态函数

cpp
#include <iostream>
#include <string>

class Counter {
private:
    static int total_count_;    // 静态数据成员
    static int active_objects_; // 活跃对象计数
    int instance_id_;           // 实例ID
    
public:
    // 构造函数
    Counter() : instance_id_(++total_count_) {
        ++active_objects_;
        std::cout << "创建Counter " << instance_id_ << std::endl;
    }
    
    // 析构函数
    ~Counter() {
        --active_objects_;
        std::cout << "销毁Counter " << instance_id_ << std::endl;
    }
    
    // 静态成员函数
    static int getTotalCount() {
        return total_count_;
    }
    
    static int getActiveObjects() {
        return active_objects_;
    }
    
    static void showStatistics() {
        std::cout << "总创建数: " << total_count_ 
                  << ", 当前活跃: " << active_objects_ << std::endl;
    }
    
    int getInstanceId() const { return instance_id_; }
};

// 静态成员定义(必须在类外定义)
int Counter::total_count_ = 0;
int Counter::active_objects_ = 0;

// 单例模式示例
class Singleton {
private:
    static Singleton* instance_;
    int value_;
    
    // 私有构造函数
    Singleton(int value = 0) : value_(value) {}
    
public:
    // 获取唯一实例
    static Singleton* getInstance() {
        if (instance_ == nullptr) {
            instance_ = new Singleton(42);
        }
        return instance_;
    }
    
    static void destroyInstance() {
        delete instance_;
        instance_ = nullptr;
    }
    
    int getValue() const { return value_; }
    void setValue(int value) { value_ = value; }
};

// 静态成员定义
Singleton* Singleton::instance_ = nullptr;

int main() {
    std::cout << "=== 静态成员 ===" << std::endl;
    
    // 静态函数可以通过类名调用
    Counter::showStatistics();
    
    {
        Counter c1, c2, c3;
        Counter::showStatistics();
        
        std::cout << "c1 ID: " << c1.getInstanceId() << std::endl;
        std::cout << "c2 ID: " << c2.getInstanceId() << std::endl;
        
        {
            Counter c4;
            Counter::showStatistics();
        }
        
        Counter::showStatistics();
    }
    
    Counter::showStatistics();
    
    // 单例模式演示
    std::cout << "\n=== 单例模式 ===" << std::endl;
    
    Singleton* s1 = Singleton::getInstance();
    Singleton* s2 = Singleton::getInstance();
    
    std::cout << "s1 == s2: " << (s1 == s2) << std::endl;
    std::cout << "单例值: " << s1->getValue() << std::endl;
    
    s1->setValue(100);
    std::cout << "通过s2获取值: " << s2->getValue() << std::endl;
    
    Singleton::destroyInstance();
    
    return 0;
}

🔧 成员函数类型

const成员函数和mutable

cpp
#include <iostream>
#include <string>

class Book {
private:
    std::string title_;
    std::string author_;
    int pages_;
    mutable int access_count_;  // mutable允许在const函数中修改
    
public:
    Book(const std::string& title, const std::string& author, int pages)
        : title_(title), author_(author), pages_(pages), access_count_(0) {}
    
    // const成员函数:不修改对象状态
    std::string getTitle() const {
        ++access_count_;  // mutable成员可以在const函数中修改
        return title_;
    }
    
    std::string getAuthor() const {
        ++access_count_;
        return author_;
    }
    
    int getPages() const {
        ++access_count_;
        return pages_;
    }
    
    int getAccessCount() const {
        return access_count_;
    }
    
    // 非const成员函数:可以修改对象状态
    void setTitle(const std::string& title) {
        title_ = title;
    }
    
    void setAuthor(const std::string& author) {
        author_ = author;
    }
    
    // const和非const重载
    char& at(size_t index) {
        std::cout << "非const版本" << std::endl;
        return title_[index];
    }
    
    const char& at(size_t index) const {
        std::cout << "const版本" << std::endl;
        return title_[index];
    }
    
    void display() const {
        std::cout << "《" << title_ << "》 - " << author_ 
                  << " (" << pages_ << "页)" 
                  << " [访问次数: " << access_count_ << "]" << std::endl;
    }
};

int main() {
    std::cout << "=== const成员函数 ===" << std::endl;
    
    Book book("C++程序设计", "Bjarne Stroustrup", 500);
    const Book const_book("设计模式", "Gang of Four", 400);
    
    // 非const对象
    std::cout << "非const对象访问:" << std::endl;
    std::cout << "标题: " << book.getTitle() << std::endl;
    std::cout << "作者: " << book.getAuthor() << std::endl;
    
    book.setTitle("C++高级编程");  // 可以调用非const函数
    book.display();
    
    // const对象
    std::cout << "\nconst对象访问:" << std::endl;
    std::cout << "标题: " << const_book.getTitle() << std::endl;
    std::cout << "作者: " << const_book.getAuthor() << std::endl;
    // const_book.setTitle("新标题");  // 错误!不能调用非const函数
    
    const_book.display();
    
    // const重载演示
    std::cout << "\n重载演示:" << std::endl;
    char ch1 = book.at(0);        // 调用非const版本
    char ch2 = const_book.at(0);  // 调用const版本
    
    return 0;
}

🎯 友元

友元函数和友元类

cpp
#include <iostream>

class Point {
private:
    double x_, y_;
    
public:
    Point(double x = 0, double y = 0) : x_(x), y_(y) {}
    
    // 友元函数声明
    friend double distance(const Point& p1, const Point& p2);
    friend std::ostream& operator<<(std::ostream& os, const Point& p);
    
    // 友元类声明
    friend class Circle;
    
    // 公有接口
    double getX() const { return x_; }
    double getY() const { return y_; }
    void setX(double x) { x_ = x; }
    void setY(double y) { y_ = y; }
};

// 友元函数定义
double distance(const Point& p1, const Point& p2) {
    double dx = p1.x_ - p2.x_;  // 可以直接访问私有成员
    double dy = p1.y_ - p2.y_;
    return std::sqrt(dx * dx + dy * dy);
}

// 重载输出运算符(友元函数)
std::ostream& operator<<(std::ostream& os, const Point& p) {
    os << "(" << p.x_ << ", " << p.y_ << ")";  // 直接访问私有成员
    return os;
}

// 友元类
class Circle {
private:
    Point center_;
    double radius_;
    
public:
    Circle(const Point& center, double radius) 
        : center_(center), radius_(radius) {}
    
    Circle(double x, double y, double radius) 
        : center_(x, y), radius_(radius) {}
    
    bool contains(const Point& p) const {
        // 可以直接访问Point的私有成员
        double dx = p.x_ - center_.x_;
        double dy = p.y_ - center_.y_;
        double dist_sq = dx * dx + dy * dy;
        return dist_sq <= radius_ * radius_;
    }
    
    void display() const {
        std::cout << "圆心: " << center_ << ", 半径: " << radius_ << std::endl;
    }
    
    double getArea() const {
        return 3.14159 * radius_ * radius_;
    }
};

int main() {
    std::cout << "=== 友元 ===" << std::endl;
    
    Point p1(3, 4);
    Point p2(6, 8);
    
    std::cout << "点1: " << p1 << std::endl;
    std::cout << "点2: " << p2 << std::endl;
    
    // 使用友元函数
    double dist = distance(p1, p2);
    std::cout << "两点间距离: " << dist << std::endl;
    
    // 友元类示例
    Circle circle(p1, 5.0);
    circle.display();
    
    std::cout << "点2是否在圆内: " << (circle.contains(p2) ? "是" : "否") << std::endl;
    
    Point p3(3, 6);
    std::cout << "点(" << p3.getX() << ", " << p3.getY() << ")是否在圆内: " 
              << (circle.contains(p3) ? "是" : "否") << std::endl;
    
    return 0;
}

🏭 对象的生命周期

对象创建和销毁

cpp
#include <iostream>
#include <memory>

class ManagedResource {
private:
    std::string name_;
    int* data_;
    
public:
    // 构造函数
    explicit ManagedResource(const std::string& name) : name_(name) {
        data_ = new int(42);
        std::cout << "创建资源: " << name_ << std::endl;
    }
    
    // 拷贝构造函数
    ManagedResource(const ManagedResource& other) : name_(other.name_ + "_copy") {
        data_ = new int(*other.data_);
        std::cout << "拷贝资源: " << name_ << std::endl;
    }
    
    // 移动构造函数 (C++11)
    ManagedResource(ManagedResource&& other) noexcept 
        : name_(std::move(other.name_)), data_(other.data_) {
        other.data_ = nullptr;
        std::cout << "移动资源: " << name_ << std::endl;
    }
    
    // 赋值运算符
    ManagedResource& operator=(const ManagedResource& other) {
        if (this != &other) {
            delete data_;
            name_ = other.name_ + "_assigned";
            data_ = new int(*other.data_);
            std::cout << "赋值资源: " << name_ << std::endl;
        }
        return *this;
    }
    
    // 移动赋值运算符 (C++11)
    ManagedResource& operator=(ManagedResource&& other) noexcept {
        if (this != &other) {
            delete data_;
            name_ = std::move(other.name_);
            data_ = other.data_;
            other.data_ = nullptr;
            std::cout << "移动赋值资源: " << name_ << std::endl;
        }
        return *this;
    }
    
    // 析构函数
    ~ManagedResource() {
        delete data_;
        std::cout << "销毁资源: " << name_ << std::endl;
    }
    
    void display() const {
        std::cout << "资源 " << name_;
        if (data_) {
            std::cout << " 值: " << *data_;
        } else {
            std::cout << " (已移动)";
        }
        std::cout << std::endl;
    }
};

// 工厂函数
ManagedResource createResource(const std::string& name) {
    return ManagedResource(name);  // 返回值优化(RVO)
}

int main() {
    std::cout << "=== 对象生命周期 ===" << std::endl;
    
    {
        std::cout << "1. 直接构造:" << std::endl;
        ManagedResource r1("原始");
        r1.display();
        
        std::cout << "\n2. 拷贝构造:" << std::endl;
        ManagedResource r2 = r1;
        r2.display();
        
        std::cout << "\n3. 移动构造:" << std::endl;
        ManagedResource r3 = std::move(r1);
        r3.display();
        r1.display();  // 已被移动
        
        std::cout << "\n4. 赋值操作:" << std::endl;
        ManagedResource r4("目标");
        r4 = r2;
        r4.display();
        
        std::cout << "\n5. 工厂函数:" << std::endl;
        auto r5 = createResource("工厂");
        r5.display();
        
        std::cout << "\n作用域结束前..." << std::endl;
    }
    
    std::cout << "作用域结束后" << std::endl;
    
    // 智能指针管理
    std::cout << "\n=== 智能指针管理 ===" << std::endl;
    {
        auto smart_res = std::make_unique<ManagedResource>("智能指针");
        smart_res->display();
    }  // 自动销毁
    
    return 0;
}

📋 类设计最佳实践

RAII和异常安全

cpp
#include <iostream>
#include <fstream>
#include <stdexcept>

// RAII (Resource Acquisition Is Initialization) 示例
class FileManager {
private:
    std::string filename_;
    std::fstream file_;
    
public:
    explicit FileManager(const std::string& filename) 
        : filename_(filename) {
        file_.open(filename_, std::ios::in | std::ios::out | std::ios::app);
        if (!file_.is_open()) {
            throw std::runtime_error("无法打开文件: " + filename_);
        }
        std::cout << "文件打开: " << filename_ << std::endl;
    }
    
    ~FileManager() {
        if (file_.is_open()) {
            file_.close();
            std::cout << "文件关闭: " << filename_ << std::endl;
        }
    }
    
    // 禁止拷贝
    FileManager(const FileManager&) = delete;
    FileManager& operator=(const FileManager&) = delete;
    
    // 移动语义
    FileManager(FileManager&& other) noexcept 
        : filename_(std::move(other.filename_)), file_(std::move(other.file_)) {
        std::cout << "文件管理器移动: " << filename_ << std::endl;
    }
    
    void write(const std::string& content) {
        if (!file_.is_open()) {
            throw std::runtime_error("文件未打开");
        }
        file_ << content << std::endl;
        file_.flush();
    }
    
    bool isOpen() const {
        return file_.is_open();
    }
};

// 设计良好的类示例
class BankAccount {
private:
    std::string account_number_;
    double balance_;
    static int next_account_id_;
    
    // 验证金额
    void validateAmount(double amount) const {
        if (amount < 0) {
            throw std::invalid_argument("金额不能为负数");
        }
    }
    
public:
    explicit BankAccount(double initial_balance = 0.0) 
        : balance_(initial_balance) {
        validateAmount(initial_balance);
        account_number_ = "ACC" + std::to_string(++next_account_id_);
        std::cout << "账户创建: " << account_number_ 
                  << " 余额: " << balance_ << std::endl;
    }
    
    ~BankAccount() {
        std::cout << "账户销毁: " << account_number_ << std::endl;
    }
    
    // 存款
    void deposit(double amount) {
        validateAmount(amount);
        balance_ += amount;
        std::cout << "存款 " << amount << ", 余额: " << balance_ << std::endl;
    }
    
    // 取款
    bool withdraw(double amount) {
        validateAmount(amount);
        if (amount > balance_) {
            std::cout << "余额不足" << std::endl;
            return false;
        }
        balance_ -= amount;
        std::cout << "取款 " << amount << ", 余额: " << balance_ << std::endl;
        return true;
    }
    
    // 查询余额
    double getBalance() const { return balance_; }
    std::string getAccountNumber() const { return account_number_; }
    
    // 转账
    bool transferTo(BankAccount& target, double amount) {
        if (withdraw(amount)) {
            target.deposit(amount);
            std::cout << "转账成功: " << account_number_ 
                      << " -> " << target.account_number_ 
                      << " 金额: " << amount << std::endl;
            return true;
        }
        return false;
    }
};

int BankAccount::next_account_id_ = 0;

int main() {
    std::cout << "=== 类设计最佳实践 ===" << std::endl;
    
    // RAII示例
    try {
        FileManager fm("test.txt");
        fm.write("这是测试内容");
        // 文件会在作用域结束时自动关闭
    } catch (const std::exception& e) {
        std::cout << "文件操作异常: " << e.what() << std::endl;
    }
    
    // 银行账户示例
    std::cout << "\n=== 银行账户操作 ===" << std::endl;
    
    try {
        BankAccount account1(1000.0);
        BankAccount account2(500.0);
        
        account1.deposit(200.0);
        account1.withdraw(150.0);
        
        account1.transferTo(account2, 300.0);
        
        std::cout << "账户1余额: " << account1.getBalance() << std::endl;
        std::cout << "账户2余额: " << account2.getBalance() << std::endl;
        
        // 异常测试
        account1.withdraw(2000.0);  // 余额不足
        
    } catch (const std::exception& e) {
        std::cout << "账户操作异常: " << e.what() << std::endl;
    }
    
    return 0;
}

总结

类和对象是C++面向对象编程的基础,提供了强大的数据抽象和封装能力:

核心概念

  • 类定义:数据成员和成员函数的封装
  • 对象实例:类的具体实现
  • 访问控制:private、protected、public
  • 生命周期:构造、使用、析构

重要特性

特性用途最佳实践
构造函数对象初始化初始化列表,RAII
析构函数资源清理确保资源释放
静态成员类级别数据/方法合理使用,避免全局变量
友元特殊访问权限谨慎使用,破坏封装

设计原则

  • 单一职责:每个类只负责一个功能
  • 封装性:隐藏内部实现细节
  • RAII:资源获取即初始化
  • 异常安全:保证程序健壮性
  • const正确性:明确接口意图

掌握类和对象的设计是进入面向对象编程世界的第一步,为后续学习继承、多态等高级特性奠定基础。

本站内容仅供学习和研究使用。