Skip to content

面向对象进阶

本章将深入探讨C++面向对象编程的高级特性,包括继承、多态、虚函数、抽象类等概念。

继承

基本继承

cpp
#include <iostream>
#include <string>
using namespace std;

// 基类(父类)
class Animal {
protected:  // 保护成员,派生类可以访问
    string name;
    int age;
    
public:
    Animal(string n = "", int a = 0) : name(n), age(a) {
        cout << "Animal构造函数" << endl;
    }
    
    virtual ~Animal() {  // 虚析构函数
        cout << "Animal析构函数" << endl;
    }
    
    void eat() {
        cout << name << "正在吃东西" << endl;
    }
    
    void sleep() {
        cout << name << "正在睡觉" << endl;
    }
    
    virtual void speak() {  // 虚函数
        cout << name << "发出声音" << endl;
    }
    
    void display() {
        cout << "姓名: " << name << ", 年龄: " << age << endl;
    }
};

// 派生类(子类)
// class 派生类 : 继承方式 基类
class Dog : public Animal {
private:
    string breed;  // 品种
    
public:
    Dog(string n, int a, string b) : Animal(n, a), breed(b) {
        cout << "Dog构造函数" << endl;
    }
    
    ~Dog() {
        cout << "Dog析构函数" << endl;
    }
    
    // 新增成员函数
    void fetch() {
        cout << name << "正在捡球" << endl;
    }
    
    // 重写基类虚函数
    void speak() override {  // override关键字(C++11)
        cout << name << "汪汪叫!" << endl;
    }
    
    void displayBreed() {
        cout << "品种: " << breed << endl;
    }
};

// 另一个派生类
class Cat : public Animal {
private:
    string color;
    
public:
    Cat(string n, int a, string c) : Animal(n, a), color(c) {
        cout << "Cat构造函数" << endl;
    }
    
    ~Cat() {
        cout << "Cat析构函数" << endl;
    }
    
    void climb() {
        cout << name << "正在爬树" << endl;
    }
    
    void speak() override {
        cout << name << "喵喵叫!" << endl;
    }
};

int main() {
    cout << "===== Dog对象 =====" << endl;
    Dog dog("旺财", 3, "金毛");
    dog.display();       // 继承自Animal
    dog.eat();           // 继承自Animal
    dog.speak();         // 重写的版本
    dog.fetch();         // Dog特有
    dog.displayBreed();
    
    cout << "\n===== Cat对象 =====" << endl;
    Cat cat("咪咪", 2, "橘色");
    cat.display();
    cat.sleep();
    cat.speak();
    cat.climb();
    
    return 0;
}

继承方式

cpp
#include <iostream>
using namespace std;

class Base {
public:
    int publicVar;
protected:
    int protectedVar;
private:
    int privateVar;
    
public:
    Base() : publicVar(1), protectedVar(2), privateVar(3) {}
};

// 公有继承
class PublicDerived : public Base {
public:
    void access() {
        publicVar = 10;      // 可以访问,仍为public
        protectedVar = 20;   // 可以访问,仍为protected
        // privateVar = 30;  // 不能访问
    }
};

// 保护继承
class ProtectedDerived : protected Base {
public:
    void access() {
        publicVar = 10;      // 可以访问,变为protected
        protectedVar = 20;   // 可以访问,仍为protected
        // privateVar = 30;  // 不能访问
    }
};

// 私有继承
class PrivateDerived : private Base {
public:
    void access() {
        publicVar = 10;      // 可以访问,变为private
        protectedVar = 20;   // 可以访问,变为private
        // privateVar = 30;  // 不能访问
    }
};

int main() {
    PublicDerived pub;
    pub.publicVar = 100;  // 可以访问
    
    ProtectedDerived pro;
    // pro.publicVar = 100;  // 不能访问,已变为protected
    
    PrivateDerived pri;
    // pri.publicVar = 100;  // 不能访问,已变为private
    
    /*
     * 继承方式对成员访问权限的影响:
     * 
     * 基类成员        公有继承        保护继承        私有继承
     * public         public         protected      private
     * protected      protected      protected      private
     * private        不可访问       不可访问       不可访问
     */
    
    return 0;
}

多态

虚函数与多态

cpp
#include <iostream>
#include <vector>
#include <memory>
using namespace std;

// 抽象基类
class Shape {
protected:
    string name;
    
public:
    Shape(string n) : name(n) {}
    
    // 纯虚函数:使类成为抽象类
    virtual double area() const = 0;
    virtual double perimeter() const = 0;
    
    // 虚函数
    virtual void display() const {
        cout << "形状: " << name << endl;
    }
    
    // 虚析构函数
    virtual ~Shape() {
        cout << "Shape析构" << endl;
    }
};

// 具体类:圆形
class Circle : public Shape {
private:
    double radius;
    
public:
    Circle(double r) : Shape("圆形"), radius(r) {}
    
    double area() const override {
        return 3.14159 * radius * radius;
    }
    
    double perimeter() const override {
        return 2 * 3.14159 * radius;
    }
    
    void display() const override {
        Shape::display();  // 调用基类版本
        cout << "半径: " << radius << endl;
        cout << "面积: " << area() << endl;
        cout << "周长: " << perimeter() << endl;
    }
    
    ~Circle() {
        cout << "Circle析构" << endl;
    }
};

// 具体类:矩形
class Rectangle : public Shape {
private:
    double width, height;
    
public:
    Rectangle(double w, double h) : Shape("矩形"), width(w), height(h) {}
    
    double area() const override {
        return width * height;
    }
    
    double perimeter() const override {
        return 2 * (width + height);
    }
    
    void display() const override {
        Shape::display();
        cout << "宽: " << width << ", 高: " << height << endl;
        cout << "面积: " << area() << endl;
        cout << "周长: " << perimeter() << endl;
    }
    
    ~Rectangle() {
        cout << "Rectangle析构" << endl;
    }
};

// 具体类:三角形
class Triangle : public Shape {
private:
    double a, b, c;  // 三边长度
    
public:
    Triangle(double a, double b, double c) 
        : Shape("三角形"), a(a), b(b), c(c) {}
    
    double area() const override {
        // 海伦公式
        double s = (a + b + c) / 2;
        return sqrt(s * (s - a) * (s - b) * (s - c));
    }
    
    double perimeter() const override {
        return a + b + c;
    }
    
    void display() const override {
        Shape::display();
        cout << "边长: " << a << ", " << b << ", " << c << endl;
        cout << "面积: " << area() << endl;
        cout << "周长: " << perimeter() << endl;
    }
};

int main() {
    // 使用基类指针实现多态
    vector<unique_ptr<Shape>> shapes;
    
    shapes.push_back(make_unique<Circle>(5.0));
    shapes.push_back(make_unique<Rectangle>(4.0, 6.0));
    shapes.push_back(make_unique<Triangle>(3.0, 4.0, 5.0));
    
    cout << "===== 多态演示 =====" << endl;
    for (const auto& shape : shapes) {
        shape->display();  // 调用各自的display
        cout << endl;
    }
    
    // 计算总面积
    double totalArea = 0;
    for (const auto& shape : shapes) {
        totalArea += shape->area();  // 多态调用
    }
    cout << "总面积: " << totalArea << endl;
    
    return 0;
}

虚函数表

cpp
#include <iostream>
using namespace std;

class Base {
public:
    virtual void func1() { cout << "Base::func1" << endl; }
    virtual void func2() { cout << "Base::func2" << endl; }
    void normalFunc() { cout << "Base::normalFunc" << endl; }
};

class Derived : public Base {
public:
    void func1() override { cout << "Derived::func1" << endl; }
    void func2() override { cout << "Derived::func2" << endl; }
    void normalFunc() { cout << "Derived::normalFunc" << endl; }
};

int main() {
    /*
     * 虚函数表(vtable):
     * 
     * 1. 每个包含虚函数的类都有一个虚函数表
     * 2. 虚函数表是一个函数指针数组
     * 3. 每个对象包含一个指向虚函数表的指针(vptr)
     * 4. 运行时通过vptr找到vtable,实现动态绑定
     */
    
    Base* ptr;
    Derived d;
    ptr = &d;
    
    // 虚函数:动态绑定(运行时决定)
    ptr->func1();  // Derived::func1
    ptr->func2();  // Derived::func2
    
    // 非虚函数:静态绑定(编译时决定)
    ptr->normalFunc();  // Base::normalFunc
    
    // 直接调用Derived的方法
    d.normalFunc();  // Derived::normalFunc
    
    return 0;
}

抽象类与接口

cpp
#include <iostream>
#include <string>
using namespace std;

// 抽象类:包含纯虚函数
class Drawable {
public:
    // 纯虚函数
    virtual void draw() const = 0;
    virtual void resize(double factor) = 0;
    
    // 虚析构函数
    virtual ~Drawable() = default;
    
    // 可以有普通成员函数
    void showInfo() {
        cout << "这是一个可绘制对象" << endl;
    }
};

// 接口:只有纯虚函数的抽象类
class Serializable {
public:
    virtual string serialize() const = 0;
    virtual void deserialize(const string& data) = 0;
    virtual ~Serializable() = default;
};

// 实现多个接口
class Shape : public Drawable, public Serializable {
protected:
    double x, y;  // 位置
    
public:
    Shape(double x = 0, double y = 0) : x(x), y(y) {}
    
    // 必须实现所有纯虚函数
    void draw() const override {
        cout << "在位置(" << x << ", " << y << ")绘制形状" << endl;
    }
    
    void resize(double factor) override {
        cout << "缩放因子: " << factor << endl;
    }
    
    string serialize() const override {
        return "Shape(" + to_string(x) + "," + to_string(y) + ")";
    }
    
    void deserialize(const string& data) override {
        // 解析数据
        cout << "反序列化: " << data << endl;
    }
};

// 具体形状类
class Circle : public Shape {
private:
    double radius;
    
public:
    Circle(double x, double y, double r) : Shape(x, y), radius(r) {}
    
    void draw() const override {
        cout << "在位置(" << x << ", " << y << ")绘制圆形,半径: " << radius << endl;
    }
    
    void resize(double factor) override {
        radius *= factor;
    }
    
    string serialize() const override {
        return "Circle(" + to_string(x) + "," + to_string(y) + "," + to_string(radius) + ")";
    }
};

int main() {
    // 不能实例化抽象类
    // Drawable d;  // 错误
    
    // 可以使用抽象类指针
    Drawable* drawable = new Circle(10, 20, 5);
    drawable->draw();
    drawable->showInfo();
    delete drawable;
    
    // 使用接口
    Serializable* serializable = new Circle(0, 0, 10);
    string data = serializable->serialize();
    cout << "\n序列化数据: " << data << endl;
    serializable->deserialize(data);
    delete serializable;
    
    return 0;
}

运算符重载

cpp
#include <iostream>
#include <string>
using namespace std;

class Complex {
private:
    double real;
    double imag;
    
public:
    Complex(double r = 0, double i = 0) : real(r), imag(i) {}
    
    // 获取器
    double getReal() const { return real; }
    double getImag() const { return imag; }
    
    // ============ 算术运算符重载 ============
    
    // 成员函数重载 +
    Complex operator+(const Complex& other) const {
        return Complex(real + other.real, imag + other.imag);
    }
    
    // 成员函数重载 -
    Complex operator-(const Complex& other) const {
        return Complex(real - other.real, imag - other.imag);
    }
    
    // 成员函数重载 *(复数乘法)
    Complex operator*(const Complex& other) const {
        return Complex(
            real * other.real - imag * other.imag,
            real * other.imag + imag * other.real
        );
    }
    
    // ============ 复合赋值运算符 ============
    
    Complex& operator+=(const Complex& other) {
        real += other.real;
        imag += other.imag;
        return *this;
    }
    
    // ============ 一元运算符 ============
    
    // 负号
    Complex operator-() const {
        return Complex(-real, -imag);
    }
    
    // ============ 比较运算符 ============
    
    bool operator==(const Complex& other) const {
        return real == other.real && imag == other.imag;
    }
    
    bool operator!=(const Complex& other) const {
        return !(*this == other);
    }
    
    // ============ 自增运算符 ============
    
    // 前置++
    Complex& operator++() {
        ++real;
        return *this;
    }
    
    // 后置++(int参数区分)
    Complex operator++(int) {
        Complex temp = *this;
        ++real;
        return temp;
    }
    
    // ============ 下标运算符 ============
    
    double& operator[](int index) {
        if (index == 0) return real;
        return imag;
    }
    
    // ============ 类型转换 ============
    
    // 转换为double(模)
    operator double() const {
        return sqrt(real * real + imag * imag);
    }
    
    // ============ 输入输出运算符(友元函数) ============
    
    friend ostream& operator<<(ostream& os, const Complex& c);
    friend istream& operator>>(istream& is, Complex& c);
};

// 输出运算符
ostream& operator<<(ostream& os, const Complex& c) {
    os << c.real;
    if (c.imag >= 0) os << "+";
    os << c.imag << "i";
    return os;
}

// 输入运算符
istream& operator>>(istream& is, Complex& c) {
    cout << "输入实部: ";
    is >> c.real;
    cout << "输入虚部: ";
    is >> c.imag;
    return is;
}

int main() {
    Complex c1(3, 4);
    Complex c2(1, 2);
    
    cout << "c1 = " << c1 << endl;
    cout << "c2 = " << c2 << endl;
    
    // 算术运算
    cout << "\nc1 + c2 = " << (c1 + c2) << endl;
    cout << "c1 - c2 = " << (c1 - c2) << endl;
    cout << "c1 * c2 = " << (c1 * c2) << endl;
    
    // 复合赋值
    Complex c3 = c1;
    c3 += c2;
    cout << "c1 += c2 = " << c3 << endl;
    
    // 一元运算
    cout << "-c1 = " << (-c1) << endl;
    
    // 比较运算
    cout << "\nc1 == c2: " << (c1 == c2) << endl;
    cout << "c1 != c2: " << (c1 != c2) << endl;
    
    // 自增运算
    Complex c4(1, 1);
    cout << "\n++c4 = " << (++c4) << endl;
    cout << "c4++ = " << (c4++) << endl;
    cout << "c4 = " << c4 << endl;
    
    // 下标运算
    c1[0] = 10;
    c1[1] = 20;
    cout << "\nc1[0] = " << c1[0] << ", c1[1] = " << c1[1] << endl;
    
    // 类型转换
    double magnitude = c1;
    cout << "\n|c1| = " << magnitude << endl;
    
    return 0;
}

本章小结

本章学习了:

  • 继承:公有、保护、私有继承
  • 多态:虚函数、动态绑定
  • 抽象类:纯虚函数、接口
  • 运算符重载:算术、比较、输入输出运算符

下一章,我们将学习模板,了解C++泛型编程。