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正确性:明确接口意图
掌握类和对象的设计是进入面向对象编程世界的第一步,为后续学习继承、多态等高级特性奠定基础。