当前位置: 首页 > article >正文

C++--------继承

一、继承的基本概念

继承是 C++ 中的一个重要特性,它允许一个类(派生类或子类)继承另一个类(基类或父类)的属性和方法。这样可以实现代码的重用和建立类之间的层次关系。

#include <iostream>

// 基类
class Base {
public:
    void show() {
        std::cout << "This is the Base class." << std::endl;
    }
};

// 派生类
class Derived : public Base {
public:
    void display() {
        std::cout << "This is the Derived class." << std::endl;
    }
};

int main() {
    Derived d;
    d.show(); // 调用基类的方法
    d.display(); // 调用派生类的方法
    return 0;
}
解释:
  • 基类Base 类包含一个公共成员函数 show()
  • 派生类Derived 类继承自 Base 类,使用 public 继承。它不仅可以访问自己的成员函数 display(),还可以访问基类的 show() 函数。

二、图形对象的继承层次

假设我们要创建一个图形对象的继承层次,可以从一个基类 Shape 开始,然后派生出具体的形状类,如 CircleRectangle 等。

#include <iostream>
#include <cmath>

class Shape {
public:
    virtual double area() = 0; // 纯虚函数,使 Shape 成为抽象类
    virtual void display() {
        std::cout << "This is a shape." << std::endl;
    }
};

class Circle : public Shape {
private:
    double radius;
public:
    Circle(double r) : radius(r) {}
    double area() override {
        return 3.14159 * radius * radius;
    }
    void display() override {
        std::cout << "This is a circle with radius " << radius << std::endl;
    }
};

class Rectangle : public Shape {
private:
    double length, width;
public:
    Rectangle(double l, double w) : length(l), width(w) {}
    double area() override {
        return length * width;
    }
    void display() override {
        std::cout << "This is a rectangle with length " << length << " and width " << width << std::endl;
    }
};

int main() {
    Circle c(5.0);
    Rectangle r(4.0, 6.0);

    Shape* s1 = &c;
    Shape* s2 = &r;

    s1->display();
    std::cout << "Area of circle: " << s1->area() << std::endl;
    s2->display();
    std::cout << "Area of rectangle: " << s2->area() << std::endl;
    return 0;
}
解释:
  • 抽象类Shape 类包含一个纯虚函数 area(),使其成为抽象类,不能被实例化。
  • 派生类CircleRectangle 继承自 Shape,并实现了 area()display() 函数。
  • 多态性:通过基类指针指向派生类对象,可以调用派生类的 display()area() 函数,实现多态性。

三、表达式的类层次

对于表达式的类层次,可以创建一个基类 Expression,然后派生出不同类型的表达式类,如 BinaryExpressionUnaryExpression 等。

#include <iostream>

class Expression {
public:
    virtual double evaluate() = 0; // 纯虚函数
    virtual void display() = 0;
};

class Constant : public Expression {
private:
    double value;
public:
    Constant(double v) : value(v) {}
    double evaluate() override {
        return value;
    }
    void display() override {
        std::cout << value;
    }
};

class BinaryExpression : public Expression {
protected:
    Expression* left;
    Expression* right;
public:
    BinaryExpression(Expression* l, Expression* r) : left(l), right(r) {}
    ~BinaryExpression() {
        delete left;
        delete right;
    }
};

class Addition : public BinaryExpression {
public:
    Addition(Expression* l, Expression* r) : BinaryExpression(l, r) {}
    double evaluate() override {
        return left->evaluate() + right->evaluate();
    }
    void display() override {
        left->display();
        std::cout << " + ";
        right->display();
    }
};

int main() {
    Expression* e1 = new Constant(5);
    Expression* e2 = new Constant(3);
    Expression* sum = new Addition(e1, e2);

    sum->display();
    std::cout << " = " << sum->evaluate() << std::endl;

    delete sum;
    return 0;
}
解释:
  • 基类Expression 是一个抽象类,包含纯虚函数 evaluate()display()
  • 派生类
    • Constant 表示常量表达式,存储一个值。
    • BinaryExpression 是一个抽象类,包含左右操作数。
    • AdditionBinaryExpression 的派生类,实现加法操作。

四、解析表达式

解析表达式可以使用递归下降解析器,结合表达式的类层次结构。例如,解析 3 + 5 这样的表达式:

  • 可以先创建 Constant 对象表示 35,然后创建 Addition 对象表示 3 + 5

五、多重继承

多重继承允许一个类继承自多个基类。

#include <iostream>

class Base1 {
public:
    void show1() {
        std::cout << "This is Base1." << std::endl;
    }
};

class Base2 {
public:
    void show2() {
        std::cout << "This is Base2." << std::endl;
    }
};

class Derived : public Base1, public Base2 {
public:
    void display() {
        std::cout << "This is Derived." << std::endl;
    }
};

int main() {
    Derived d;
    d.show1();
    d.show2();
    d.display();
    return 0;
}
解释:
  • 多重继承Derived 类继承自 Base1Base2,因此可以访问 Base1Base2 的成员函数,以及自己的成员函数。

注意事项

  • 多重继承的二义性:当多个基类有相同的成员函数或变量时,可能会产生二义性问题。可以使用作用域解析运算符 :: 来消除二义性。
  • 虚继承:在菱形继承结构中,使用虚继承可以避免重复继承相同基类的问题。
#include <iostream>

class GrandParent {
public:
    void show() {
        std::cout << "This is GrandParent." << std::endl;
    }
};

class Parent1 : virtual public GrandParent {};
class Parent2 : virtual public GrandParent {};
class Child : public Parent1, public Parent2 {};

int main() {
    Child c;
    c.show(); // 不会产生二义性
    return 0;
}

总结

  • 继承:允许代码重用和建立类层次关系,派生类继承基类的成员。
  • 图形对象继承层次:可以创建抽象基类和派生类表示不同形状,实现多态性。
  • 表达式类层次:使用继承实现不同类型的表达式,便于扩展和解析表达式。
  • 多重继承:一个类可以继承多个基类,但要注意二义性和菱形继承问题,可以使用虚继承解决。

在这里插入图片描述


http://www.kler.cn/a/454648.html

相关文章:

  • 了解jvm -server和-client 参数
  • 【ETCD】【实操篇(十八)】ETCD监控实战:提升系统健康与集群调试效率
  • platform_msi使用
  • 【Git】—— 使用git操作远程仓库(gitee)
  • httpclient GET 和POST 请求
  • Qt存储大整数到`JsonValue`
  • 赋能开发者 | 麒麟信安受邀参加2024开放原子开发者大会,以技术为引领,以人才创发展
  • 解读DeepseekV3
  • Go+chromedp实现Web UI自动化测试
  • uniapp 文本转语音
  • 挑战一个月基本掌握C++(第十二天)了解命名空间,模板,预处理器
  • 前端Python应用指南(五)用FastAPI快速构建高性能API
  • 同步异步日志系统:设计模式
  • ubuntu 账号从文本中的1000,改成0,后五笔输入法等中文输入法不可用,如何改回来
  • 【Ubuntu 20.4安装截图软件 flameshot 】
  • 全面Kafka监控方案:从配置到指标
  • 【自由能系列(初级),论文解读】神经网络中,熵代表系统的不确定性,自由能则引导系统向更低能量的状态演化,而动力学则描述了系统状态随时间的变化。
  • flask后端开发(11):User模型创建+注册页面模板渲染
  • 使用Python实现自动化文档生成工具:提升文档编写效率的利器
  • STM32F103RCT6学习之一:基本开发流程