04-面向对象编程基础
面向对象编程(OOP)是C++的核心特性,通过封装、继承、多态三大特性构建复杂系统。
类和对象
类是对象的模板,对象是类的实例。类定义了数据(成员变量)和操作(成员函数)。
类定义
类使用 class 关键字定义,默认成员为私有。良好的类设计遵循封装原则。
class Person {
private:
string name;
int age;
public:
// 构造函数
Person(string n, int a) : name(n), age(a) {}
// 成员函数
void display() {
cout << "Name: " << name << ", Age: " << age << endl;
}
// 访问器
string getName() const { return name; }
int getAge() const { return age; }
// 修改器
void setName(const string& n) { name = n; }
void setAge(int a) { age = a; }
};
对象创建和使用
Person p1("Alice", 25); // 栈上创建
Person* p2 = new Person("Bob", 30); // 堆上创建
p1.display(); // 调用成员函数
delete p2; // 释放堆内存
访问控制
public:公开访问
private:私有访问(默认)
protected:受保护访问
构造函数和析构函数
构造函数负责对象初始化,析构函数负责资源清理。它们是RAII模式的基础。
构造函数
构造函数与类同名,无返回值。支持重载、默认参数、初始化列表等特性。
class Rectangle {
private:
int width, height;
public:
// 默认构造函数
Rectangle() : width(0), height(0) {}
// 参数化构造函数
Rectangle(int w, int h) : width(w), height(h) {}
// 拷贝构造函数
Rectangle(const Rectangle& other)
: width(other.width), height(other.height) {}
// 移动构造函数(C++11)
Rectangle(Rectangle&& other) noexcept
: width(other.width), height(other.height) {
other.width = other.height = 0;
}
};
析构函数
class Resource {
private:
int* data;
public:
Resource(int size) : data(new int[size]) {}
// 析构函数
~Resource() {
delete[] data;
}
};
初始化列表
class Student {
private:
string name;
int id;
const int grade;
public:
// 初始化列表
Student(string n, int i, int g)
: name(n), id(i), grade(g) {}
};
继承
继承实现代码复用和类层次结构。派生类继承基类的属性和方法,可扩展或重写功能。
单继承
单继承指一个类只继承一个基类。使用 public、protected 或 private 指定继承方式。
// 基类
class Animal {
protected:
string species;
public:
Animal(string s) : species(s) {}
virtual void makeSound() {
cout << "Animal sound" << endl;
}
virtual ~Animal() = default;
};
// 派生类
class Dog : public Animal {
public:
Dog() : Animal("Canine") {}
void makeSound() override {
cout << "Woof!" << endl;
}
};
访问修饰符
public继承:保持原有访问级别
protected继承:public变为protected
private继承:所有成员变为private
多重继承
class Flyable {
public:
virtual void fly() = 0;
};
class Swimmable {
public:
virtual void swim() = 0;
};
class Duck : public Animal, public Flyable, public Swimmable {
public:
void fly() override {
cout << "Duck flying" << endl;
}
void swim() override {
cout << "Duck swimming" << endl;
}
};
多态
多态允许通过基类指针调用派生类方法,实现运行时决策。是面向对象三大特性之一。
虚函数
虚函数通过 virtual 关键字声明,支持运行时动态绑定。派生类用 override 明确重写意图。
class Shape {
public:
virtual double area() const = 0; // 纯虚函数
virtual void draw() const {
cout << "Drawing shape" << endl;
}
virtual ~Shape() = default;
};
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) {}
double area() const override {
return 3.14159 * radius * radius;
}
void draw() const override {
cout << "Drawing circle" << endl;
}
};
虚函数表
vtable:存储虚函数地址的表
vptr:指向虚函数表的指针
动态绑定:运行时确定调用哪个函数
抽象类
class AbstractShape {
public:
virtual double area() const = 0; // 纯虚函数
virtual double perimeter() const = 0; // 纯虚函数
// 可以有非虚函数
void printInfo() {
cout << "Area: " << area() << endl;
cout << "Perimeter: " << perimeter() << endl;
}
};
封装
数据封装
class BankAccount {
private:
double balance;
string accountNumber;
public:
BankAccount(string accNum, double initialBalance)
: accountNumber(accNum), balance(initialBalance) {}
// 公共接口
void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
bool withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
return true;
}
return false;
}
double getBalance() const {
return balance;
}
};
友元函数和友元类
class Rectangle {
private:
int width, height;
public:
Rectangle(int w, int h) : width(w), height(h) {}
// 友元函数
friend void printDimensions(const Rectangle& r);
// 友元类
friend class RectangleHelper;
};
void printDimensions(const Rectangle& r) {
cout << "Width: " << r.width << ", Height: " << r.height << endl;
}
运算符重载
基本运算符重载
class Vector {
private:
double x, y;
public:
Vector(double x = 0, double y = 0) : x(x), y(y) {}
// 加法运算符
Vector operator+(const Vector& other) const {
return Vector(x + other.x, y + other.y);
}
// 赋值运算符
Vector& operator=(const Vector& other) {
if (this != &other) {
x = other.x;
y = other.y;
}
return *this;
}
// 输出运算符(友元函数)
friend ostream& operator<<(ostream& os, const Vector& v) {
os << "(" << v.x << ", " << v.y << ")";
return os;
}
};
特殊运算符
class Array {
private:
int* data;
int size;
public:
// 下标运算符
int& operator[](int index) {
return data[index];
}
const int& operator[](int index) const {
return data[index];
}
// 函数调用运算符
int operator()(int index) const {
return data[index];
}
};
静态成员
静态数据成员
class Counter {
private:
static int count; // 静态数据成员
public:
Counter() { count++; }
~Counter() { count--; }
static int getCount() { // 静态成员函数
return count;
}
};
int Counter::count = 0; // 静态成员定义
静态成员函数
属于类而不是对象
不能访问非静态成员
可以通过类名直接调用
没有this指针
三法则/五法则/零法则
三法则(Rule of Three)
如果类需要自定义析构函数、拷贝构造或拷贝赋值中的任何一个,通常需要同时定义全部三个。
class Resource {
private:
int* data;
public:
Resource(int val) : data(new int(val)) {}
// 1. 析构函数
~Resource() { delete data; }
// 2. 拷贝构造函数
Resource(const Resource& other) : data(new int(*other.data)) {}
// 3. 拷贝赋值运算符
Resource& operator=(const Resource& other) {
if (this != &other) {
delete data;
data = new int(*other.data);
}
return *this;
}
};
五法则(Rule of Five)- C++11
C++11引入移动语义,需额外定义移动构造和移动赋值。
class Resource {
private:
int* data;
public:
Resource(int val) : data(new int(val)) {}
~Resource() { delete data; }
// 拷贝操作
Resource(const Resource& other) : data(new int(*other.data)) {}
Resource& operator=(const Resource& other) {
if (this != &other) {
delete data;
data = new int(*other.data);
}
return *this;
}
// 4. 移动构造函数
Resource(Resource&& other) noexcept : data(other.data) {
other.data = nullptr;
}
// 5. 移动赋值运算符
Resource& operator=(Resource&& other) noexcept {
if (this != &other) {
delete data;
data = other.data;
other.data = nullptr;
}
return *this;
}
};
零法则(Rule of Zero)- 推荐
使用智能指针和RAII类,让编译器自动生成所有特殊成员函数。
// ✅ 推荐:零法则
class GoodResource {
std::unique_ptr<int> data; // 自动管理内存
public:
GoodResource(int val) : data(std::make_unique<int>(val)) {}
// 编译器自动生成析构、移动操作
// 拷贝操作被隐式删除(unique_ptr不可拷贝)
};
最佳实践:优先零法则 > 五法则 > 三法则