c++指南 继承和多态

继承和多态

继承的概念

继承是面向对象编程的一个重要特性,它允许新创建的类(称为子类或派生类)继承现有类(称为基类或父类)的属性和方法。

基类与子类

基类:提供了可以被继承的属性和方法。
子类:继承了基类的属性和方法,并且可以添加新的属性和方法或重写继承的方法。

继承的类型

公有继承(public):子类继承基类的公有成员和保护成员,并且它们在子类中也是公有或保护的。
私有继承(private):子类继承基类的公有和保护成员,但它们在子类中变为私有的。
保护继承(protected):子类继承基类的公有和保护成员,但它们在子类中变为保护的。

多态性

多态性是对象可以有多种形式的能力。在C++中,多态性主要通过虚函数实现。

虚函数

虚函数是基类中的函数,允许在派生类中被重写(Override)。使用 virtual 关键字声明。

class Base {
public:
    virtual void show() { std::cout << "Base show" << std::endl; }
};

class Derived : public Base {
public:
    void show() override { std::cout << "Derived show" << std::endl; }
};

抽象类

抽象类是不能被实例化的类,它至少包含一个纯虚函数。使用 = 0 来定义纯虚函数。

class AbstractBase {
public:
    virtual void pureVirtualFunc() = 0; // 纯虚函数
};

class ConcreteClass : public AbstractBase {
public:
    void pureVirtualFunc() override {
        // 实现抽象类中的纯虚函数
    }
};

多态的实现

使用基类指针或引用指向派生类对象,可以实现动态多态性。

Base* basePtr = new Derived();
basePtr->show(); // 输出 "Derived show",展示了多态性
delete basePtr;

虚析构函数

在C++中,如果一个类是多态基类(即有一个或多个虚函数),则其析构函数应当被声明为虚函数。这是因为当通过基类指针删除派生类对象时,需要确保正确地调用派生类的析构函数,然后才是基类的析构函数。

class Base {
public:
    virtual ~Base() {
        std::cout << "Base destructor" << std::endl;
    }
};

class Derived : public Base {
public:
    ~Derived() {
        std::cout << "Derived destructor" << std::endl;
    }
};

int main() {
    Base* basePtr = new Derived();
    delete basePtr; // 正确地调用Derived和Base的析构函数
    return 0;
}
输出为
Derived destructor
Base destructor

运算符重载与多态

运算符重载允许你定义类的运算符如何工作。当运算符被重载为成员函数时,它可以是虚函数,从而支持多态性。

例子

  1. 使用虚函数重载 == 运算符
class Base {
public:
    virtual bool operator==(const Base& other) const {
        // 默认实现,可能需要根据实际需求重写
        return this == &other;
    }
};

class Derived : public Base {
    int value;
public:
    Derived(int v) : value(v) {}

    bool operator==(const Base& other) const override {
        // 重写 == 运算符以比较 Derived 对象
        const Derived* otherDerived = dynamic_cast<const Derived*>(&other);
        if (otherDerived) {
            return value == otherDerived->value;
        }
        return false;
    }
};
  1. 重载输出流运算符 <<
class Person {
    std::string name;
public:
    Person(const std::string& n) : name(n) {}

    friend std::ostream& operator<<(std::ostream& os, const Person& p) {
        os << "Person: " << p.name;
        return os;
    }
};

class Employee : public Person {
    int id;
public:
    Employee(const std::string& n, int i) : Person(n), id(i) {}

    friend std::ostream& operator<<(std::ostream& os, const Employee& e) {
        os << static_cast<const Person&>(e); // 调用基类的输出
        os << ", ID: " << e.id;
        return os;
    }
};

在这个例子中,Employee 类重载了 << 运算符,输出 Employee 对象时,首先调用了基类 Person 的 << 运算符,然后添加了 Employee 特有的信息。

  1. 重载赋值运算符 =
class Data {
    int* array;
    size_t size;
public:
    Data(size_t s) : size(s), array(new int[s]) {}

    Data(const Data& other) : size(other.size), array(new int[other.size]) {
        std::copy(other.array, other.array + size, array);
    }

    Data& operator=(const Data& other) {
        if (this != &other) {
            delete[] array;
            size = other.size;
            array = new int[size];
            std::copy(other.array, other.array + size, array);
        }
        return *this;
    }

    ~Data() {
        delete[] array;
    }
};

在这个例子中,赋值运算符 = 被重载以确保深拷贝数组,并且正确地处理自赋值的情况。

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值