Skip to content

C++ 多态

概述

多态(Polymorphism)是面向对象编程的核心特性,允许同一接口表现出不同的行为。C++通过虚函数机制实现运行时多态,通过函数重载和模板实现编译时多态。多态提高了代码的灵活性和可扩展性。

🎭 运行时多态

虚函数和动态绑定

cpp
#include <iostream>
#include <vector>
#include <memory>

class Animal {
protected:
    std::string name_;
    
public:
    Animal(const std::string& name) : name_(name) {}
    
    // 虚析构函数
    virtual ~Animal() {
        std::cout << "Animal析构: " << name_ << std::endl;
    }
    
    // 纯虚函数
    virtual void makeSound() const = 0;
    virtual void move() const = 0;
    
    // 虚函数
    virtual void eat() const {
        std::cout << name_ << " 正在吃东西" << std::endl;
    }
    
    // 非虚函数
    void sleep() const {
        std::cout << name_ << " 正在睡觉" << std::endl;
    }
    
    std::string getName() const { return name_; }
};

class Dog : public Animal {
public:
    Dog(const std::string& name) : Animal(name) {}
    
    ~Dog() {
        std::cout << "Dog析构: " << name_ << std::endl;
    }
    
    void makeSound() const override {
        std::cout << name_ << " 汪汪叫" << std::endl;
    }
    
    void move() const override {
        std::cout << name_ << " 在地上跑" << std::endl;
    }
    
    void eat() const override {
        std::cout << name_ << " 吃狗粮" << std::endl;
    }
    
    // 子类特有方法
    void wagTail() const {
        std::cout << name_ << " 摇尾巴" << std::endl;
    }
};

class Bird : public Animal {
public:
    Bird(const std::string& name) : Animal(name) {}
    
    ~Bird() {
        std::cout << "Bird析构: " << name_ << std::endl;
    }
    
    void makeSound() const override {
        std::cout << name_ << " 啁啾叫" << std::endl;
    }
    
    void move() const override {
        std::cout << name_ << " 在天空飞" << std::endl;
    }
    
    void fly() const {
        std::cout << name_ << " 展翅高飞" << std::endl;
    }
};

int main() {
    std::cout << "=== 运行时多态 ===" << std::endl;
    
    // 多态容器
    std::vector<std::unique_ptr<Animal>> animals;
    animals.push_back(std::make_unique<Dog>("旺财"));
    animals.push_back(std::make_unique<Bird>("小鸟"));
    animals.push_back(std::make_unique<Dog>("来福"));
    
    // 多态调用
    for (const auto& animal : animals) {
        std::cout << "\n--- " << animal->getName() << " ---" << std::endl;
        animal->makeSound();  // 虚函数调用
        animal->move();       // 虚函数调用
        animal->eat();        // 虚函数调用
        animal->sleep();      // 非虚函数调用
    }
    
    std::cout << "\n销毁对象..." << std::endl;
    
    return 0;
}

虚函数表机制

cpp
#include <iostream>
#include <typeinfo>

class Base {
public:
    virtual ~Base() = default;
    virtual void func1() const { std::cout << "Base::func1" << std::endl; }
    virtual void func2() const { std::cout << "Base::func2" << std::endl; }
    void nonVirtualFunc() const { std::cout << "Base::nonVirtualFunc" << std::endl; }
};

class Derived : public Base {
public:
    void func1() const override { std::cout << "Derived::func1" << std::endl; }
    // func2继承自Base
    void func3() const { std::cout << "Derived::func3" << std::endl; }
};

// 演示虚函数调用
void callVirtualFunctions(const Base& obj) {
    std::cout << "对象类型: " << typeid(obj).name() << std::endl;
    obj.func1();  // 动态绑定
    obj.func2();  // 动态绑定
    obj.nonVirtualFunc();  // 静态绑定
}

int main() {
    std::cout << "=== 虚函数表机制 ===" << std::endl;
    
    Base base;
    Derived derived;
    
    std::cout << "直接调用:" << std::endl;
    callVirtualFunctions(base);
    std::cout << std::endl;
    callVirtualFunctions(derived);
    
    std::cout << "\n指针调用:" << std::endl;
    Base* ptr = &derived;
    ptr->func1();  // 调用Derived::func1
    ptr->func2();  // 调用Base::func2
    
    // 类型转换
    if (Derived* d_ptr = dynamic_cast<Derived*>(ptr)) {
        d_ptr->func3();  // 调用派生类特有方法
    }
    
    return 0;
}

🎨 抽象类和接口

纯虚函数和抽象类

cpp
#include <iostream>
#include <vector>
#include <memory>

// 抽象基类 - 图形接口
class Shape {
protected:
    std::string name_;
    
public:
    Shape(const std::string& name) : name_(name) {}
    virtual ~Shape() = default;
    
    // 纯虚函数
    virtual double getArea() const = 0;
    virtual double getPerimeter() const = 0;
    virtual void draw() const = 0;
    
    // 虚函数(有默认实现)
    virtual void display() const {
        std::cout << name_ << " - 面积: " << getArea() 
                  << ", 周长: " << getPerimeter() << std::endl;
    }
    
    std::string getName() const { return name_; }
};

class Rectangle : public Shape {
private:
    double width_, height_;
    
public:
    Rectangle(double width, double height) 
        : Shape("矩形"), width_(width), height_(height) {}
    
    double getArea() const override {
        return width_ * height_;
    }
    
    double getPerimeter() const override {
        return 2 * (width_ + height_);
    }
    
    void draw() const override {
        std::cout << "绘制矩形: " << width_ << " x " << height_ << std::endl;
    }
};

class Circle : public Shape {
private:
    double radius_;
    static constexpr double PI = 3.14159;
    
public:
    Circle(double radius) : Shape("圆形"), radius_(radius) {}
    
    double getArea() const override {
        return PI * radius_ * radius_;
    }
    
    double getPerimeter() const override {
        return 2 * PI * radius_;
    }
    
    void draw() const override {
        std::cout << "绘制圆形: 半径 " << radius_ << std::endl;
    }
};

// 接口模式
class Drawable {
public:
    virtual ~Drawable() = default;
    virtual void draw() const = 0;
};

class Resizable {
public:
    virtual ~Resizable() = default;
    virtual void resize(double factor) = 0;
};

// 多接口实现
class ScalableRectangle : public Shape, public Drawable, public Resizable {
private:
    double width_, height_;
    
public:
    ScalableRectangle(double width, double height) 
        : Shape("可缩放矩形"), width_(width), height_(height) {}
    
    double getArea() const override { return width_ * height_; }
    double getPerimeter() const override { return 2 * (width_ + height_); }
    
    void draw() const override {
        std::cout << "绘制可缩放矩形: " << width_ << " x " << height_ << std::endl;
    }
    
    void resize(double factor) override {
        width_ *= factor;
        height_ *= factor;
        std::cout << "缩放矩形,新尺寸: " << width_ << " x " << height_ << std::endl;
    }
};

int main() {
    std::cout << "=== 抽象类和接口 ===" << std::endl;
    
    // 不能实例化抽象类
    // Shape shape;  // 错误!
    
    std::vector<std::unique_ptr<Shape>> shapes;
    shapes.push_back(std::make_unique<Rectangle>(5, 3));
    shapes.push_back(std::make_unique<Circle>(4));
    shapes.push_back(std::make_unique<ScalableRectangle>(2, 6));
    
    for (const auto& shape : shapes) {
        shape->draw();
        shape->display();
        std::cout << std::endl;
    }
    
    // 接口使用
    ScalableRectangle scalable(3, 4);
    Resizable* resizable = &scalable;
    resizable->resize(1.5);
    
    return 0;
}

🔧 编译时多态

函数模板多态

cpp
#include <iostream>
#include <string>
#include <vector>

// 函数模板实现编译时多态
template<typename T>
void print(const T& value) {
    std::cout << "通用打印: " << value << std::endl;
}

// 模板特化
template<>
void print<std::string>(const std::string& value) {
    std::cout << "字符串打印: \"" << value << "\"" << std::endl;
}

template<typename Container>
void printContainer(const Container& container) {
    std::cout << "容器内容: ";
    for (const auto& item : container) {
        std::cout << item << " ";
    }
    std::cout << std::endl;
}

// 概念约束(C++20风格的模拟)
template<typename T>
void processNumeric(const T& value) {
    static_assert(std::is_arithmetic_v<T>, "T必须是数值类型");
    std::cout << "处理数值: " << value * 2 << std::endl;
}

// CRTP (Curiously Recurring Template Pattern)
template<typename Derived>
class Animal {
public:
    void makeSound() const {
        static_cast<const Derived*>(this)->makeSound();
    }
    
    void move() const {
        static_cast<const Derived*>(this)->move();
    }
};

class Dog : public Animal<Dog> {
public:
    void makeSound() const {
        std::cout << "汪汪叫" << std::endl;
    }
    
    void move() const {
        std::cout << "跑步" << std::endl;
    }
};

class Bird : public Animal<Bird> {
public:
    void makeSound() const {
        std::cout << "啁啾叫" << std::endl;
    }
    
    void move() const {
        std::cout << "飞行" << std::endl;
    }
};

int main() {
    std::cout << "=== 编译时多态 ===" << std::endl;
    
    // 函数模板多态
    print(42);
    print(3.14);
    print(std::string("Hello"));
    
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    printContainer(numbers);
    
    // 数值类型处理
    processNumeric(10);
    processNumeric(3.14);
    // processNumeric(std::string("test"));  // 编译错误
    
    // CRTP多态
    Dog dog;
    Bird bird;
    
    dog.makeSound();
    dog.move();
    
    bird.makeSound();
    bird.move();
    
    return 0;
}

类模板多态

cpp
#include <iostream>
#include <memory>

// 类模板
template<typename T>
class Stack {
private:
    struct Node {
        T data;
        std::unique_ptr<Node> next;
        Node(const T& value) : data(value), next(nullptr) {}
    };
    
    std::unique_ptr<Node> top_;
    size_t size_;
    
public:
    Stack() : top_(nullptr), size_(0) {}
    
    void push(const T& value) {
        auto new_node = std::make_unique<Node>(value);
        new_node->next = std::move(top_);
        top_ = std::move(new_node);
        ++size_;
    }
    
    void pop() {
        if (top_) {
            top_ = std::move(top_->next);
            --size_;
        }
    }
    
    const T& top() const {
        if (!top_) throw std::runtime_error("空栈");
        return top_->data;
    }
    
    bool empty() const { return top_ == nullptr; }
    size_t size() const { return size_; }
};

// 模板特化示例
template<>
class Stack<bool> {
private:
    std::vector<bool> data_;
    
public:
    void push(bool value) {
        data_.push_back(value);
    }
    
    void pop() {
        if (!data_.empty()) {
            data_.pop_back();
        }
    }
    
    bool top() const {
        if (data_.empty()) throw std::runtime_error("空栈");
        return data_.back();
    }
    
    bool empty() const { return data_.empty(); }
    size_t size() const { return data_.size(); }
};

int main() {
    std::cout << "=== 类模板多态 ===" << std::endl;
    
    // 整数栈
    Stack<int> int_stack;
    int_stack.push(1);
    int_stack.push(2);
    int_stack.push(3);
    
    std::cout << "整数栈: ";
    while (!int_stack.empty()) {
        std::cout << int_stack.top() << " ";
        int_stack.pop();
    }
    std::cout << std::endl;
    
    // 字符串栈
    Stack<std::string> str_stack;
    str_stack.push("第一个");
    str_stack.push("第二个");
    
    std::cout << "字符串栈: ";
    while (!str_stack.empty()) {
        std::cout << str_stack.top() << " ";
        str_stack.pop();
    }
    std::cout << std::endl;
    
    // 特化的bool栈
    Stack<bool> bool_stack;
    bool_stack.push(true);
    bool_stack.push(false);
    bool_stack.push(true);
    
    std::cout << "布尔栈: ";
    while (!bool_stack.empty()) {
        std::cout << (bool_stack.top() ? "true" : "false") << " ";
        bool_stack.pop();
    }
    std::cout << std::endl;
    
    return 0;
}

📋 多态设计模式

策略模式

cpp
#include <iostream>
#include <memory>
#include <vector>

class SortStrategy {
public:
    virtual ~SortStrategy() = default;
    virtual void sort(std::vector<int>& data) const = 0;
    virtual std::string getName() const = 0;
};

class BubbleSort : public SortStrategy {
public:
    void sort(std::vector<int>& data) const override {
        for (size_t i = 0; i < data.size(); ++i) {
            for (size_t j = 0; j < data.size() - 1 - i; ++j) {
                if (data[j] > data[j + 1]) {
                    std::swap(data[j], data[j + 1]);
                }
            }
        }
    }
    
    std::string getName() const override { return "冒泡排序"; }
};

class QuickSort : public SortStrategy {
public:
    void sort(std::vector<int>& data) const override {
        std::sort(data.begin(), data.end());
    }
    
    std::string getName() const override { return "快速排序"; }
};

class SortContext {
private:
    std::unique_ptr<SortStrategy> strategy_;
    
public:
    void setStrategy(std::unique_ptr<SortStrategy> strategy) {
        strategy_ = std::move(strategy);
    }
    
    void executeSort(std::vector<int>& data) {
        if (strategy_) {
            std::cout << "使用" << strategy_->getName() << std::endl;
            strategy_->sort(data);
        }
    }
};

int main() {
    std::cout << "=== 策略模式 ===" << std::endl;
    
    std::vector<int> data1 = {64, 34, 25, 12, 22, 11, 90};
    std::vector<int> data2 = data1;
    
    SortContext context;
    
    context.setStrategy(std::make_unique<BubbleSort>());
    context.executeSort(data1);
    
    context.setStrategy(std::make_unique<QuickSort>());
    context.executeSort(data2);
    
    std::cout << "排序结果: ";
    for (int n : data1) std::cout << n << " ";
    std::cout << std::endl;
    
    return 0;
}

总结

多态是C++面向对象编程的核心,提供了灵活的代码设计方案:

多态类型

  • 运行时多态:虚函数、动态绑定
  • 编译时多态:模板、函数重载
  • 抽象多态:纯虚函数、接口设计

实现机制

多态类型实现方式性能灵活性
运行时虚函数表轻微开销
编译时模板展开无开销中等
重载名称修饰无开销

设计原则

  • 基类析构函数声明为virtual
  • 优先使用组合而非继承
  • 接口与实现分离
  • 遵循开闭原则
  • 合理选择多态类型

多态让程序具有良好的扩展性和维护性,是构建大型软件系统的重要工具。

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