C++中设计三种不同继承方式的意义

Posted 草原上唱山歌

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++中设计三种不同继承方式的意义相关的知识,希望对你有一定的参考价值。

在C++中,继承是一种面向对象编程的核心概念之一。继承可以使得一个类(子类)可以从另一个类(父类)继承属性和方法。在C++中,有三种不同的继承方式:public继承、protected继承和private继承。每种继承方式都有其自身的意义和使用场景。

public继承

public继承是最常见的一种继承方式,也是默认的继承方式。在public继承中,子类可以访问父类的public成员,但是不能访问父类的private成员。public继承的意义在于,可以使得子类继承父类的接口(public成员),从而使得子类可以更方便地使用父类的方法和属性。

protected继承

protected继承是一种介于public继承和private继承之间的继承方式。在protected继承中,子类可以访问父类的protected成员和public成员,但是不能访问父类的private成员。protected继承的意义在于,可以使得子类能够访问父类的protected成员,从而使得子类可以重用父类的实现,而不用对外暴露父类的实现细节。

private继承

private继承是一种最严格的继承方式。在private继承中,子类可以访问父类的protectedpublic成员,但是不能访问父类的private成员。private继承的意义在于,可以使得子类不能直接使用父类的接口,而是需要通过自己的方法来实现。这种方式一般用于实现细节隐藏,即不希望子类能够访问父类的实现细节。

C++中的继承方式设计是为了实现代码的重用和继承,同时也可以实现对代码实现细节的隐藏和保护。不同的继承方式可以在不同的场景下发挥作用。

假设我们有一个动物类 Animal,以及三个派生类 DogCatBird,分别继承自 Animal。下面给出使用不同继承方式的代码示例:

public 继承

class Animal 
public:
    void eat() 
        cout << "Animal is eating" << endl;
    
;

class Dog : public Animal 
public:
    void bark() 
        cout << "Dog is barking" << endl;
    
;

class Cat : public Animal 
public:
    void meow() 
        cout << "Cat is meowing" << endl;
    
;

class Bird : public Animal 
public:
    void fly() 
        cout << "Bird is flying" << endl;
    
;

这里的 DogCatBird 都是以 public 方式继承 Animal 类。这意味着它们可以访问 Animal 类中的公共成员(如 eat() 函数),并将其作为自己的公共成员。

protected 继承

class Animal 
protected:
    void eat() 
        cout << "Animal is eating" << endl;
    
;

class Dog : protected Animal 
public:
    void bark() 
        cout << "Dog is barking" << endl;
        eat();
    
;

class Cat : protected Animal 
public:
    void meow() 
        cout << "Cat is meowing" << endl;
        eat();
    
;

class Bird : protected Animal 
public:
    void fly() 
        cout << "Bird is flying" << endl;
        eat();
    
;

这里的 DogCatBird 都是以 protected 方式继承 Animal 类。这意味着它们可以访问 Animal 类中的保护成员(如 eat() 函数),并将其作为自己的保护成员。由于 eat() 函数是保护成员,因此在 DogCatBird 中都可以直接访问它。

private 继承

class Animal 
private:
    void eat() 
        cout << "Animal is eating" << endl;
    
;

class Dog : private Animal 
public:
    void bark() 
        cout << "Dog is barking" << endl;
        eat();
    
;

class Cat : private Animal 
public:
    void meow() 
        cout << "Cat is meowing" << endl;
        eat();
    
;

class Bird : private Animal 
public:
    void fly() 
        cout << "Bird is flying" << endl;
        eat();
    
;

这里的 DogCatBird 都是以 private 方式继承 Animal 类。这意味着它们无法访问 Animal 类中的公共或保护成员,而只能将其作为自己的私有成员。由于 eat() 函数是私有成员,因此在 DogCatBird 中都无法直接访问它,只能通过 Animal 中公开的接口(如 eat() 函数的调用)来访问它。

为了能够解释得更加清楚,比如如下例子:

假设我们正在编写一个游戏,这个游戏有多个角色,每个角色都有自己的属性(如血量、攻击力等)和行为(如移动、攻击等),并且角色之间有不同的关系(如团队关系、敌对关系等)。我们使用C++来实现这个游戏。

首先,我们需要一个基类来表示所有角色的共同属性和行为。我们可以定义一个叫做“Character”的类,其中包含角色的基本属性和行为,如下所示:

class Character 
protected:
    int health;
    int attackPower;
public:
    virtual void move(int x, int y) = 0;
    virtual void attack(Character& target) = 0;
;

在这个类中,我们使用了protected访问修饰符,这意味着子类可以访问这些属性和方法,但其他类不能访问它们。同时,我们还使用了纯虚函数,这是一种只声明而不实现的函数,它告诉编译器这些函数需要在子类中被重写。

接下来,我们可以定义一些子类来表示不同类型的角色。例如,我们可以定义一个“Warrior”类,表示一名战士,如下所示:

class Warrior : public Character 
public:
    Warrior() 
        health = 100;
        attackPower = 10;
    
    void move(int x, int y) override 
        // 移动逻辑
    
    void attack(Character& target) override 
        // 攻击逻辑
    
;

在这个类中,我们使用了public继承,这意味着子类继承了父类的所有属性和方法,并且这些属性和方法都是public的,可以被其他类访问。同时,我们重写了基类中的纯虚函数,实现了战士的具体行为。

除了战士,我们还可以定义其他类型的角色,如法师、弓箭手等等。这些角色都继承自基类“Character”,并且根据不同的需求,可以使用不同的继承方式。

例如,我们可以定义一个“Wizard”类,表示一名法师,如下所示:

class Wizard : protected Character 
public:
    Wizard() 
        health = 50;
        attackPower = 20;
    
    void move(int x, int y) override 
        // 移动逻辑
    
    void attack(Character& target) override 
        // 攻击逻辑
    
;

在这个类中,我们使用了protected继承,这意味着子类继承了父类的所有属性和方法,但这些属性和方法都是protected的,不能被其他类访问。

private继承大家可以根据上述讲解自行实现,动手操作一下,有助于自己理解。

C++--继承的概念和意义继承中的访问级别不同的继承方式

一.继承的概念和意义

Q:类之间是否存在直接的关联关系?
由这个问题由此联想到生活中的例子:组合
A.组合关系:整体与部分的关系
技术图片
组合关系的描述--代码示例

#include <iostream>
#include <string>

using namespace std;

class Memory

public:
    Memory()
    
        cout << "Memory()" << endl;
    
    ~Memory()
    
        cout << "~Memory()" << endl;
    
;

class Disk

public:
    Disk()
    
        cout << "Disk()" << endl;
    
    ~Disk()
    
        cout << "~Disk()" << endl;
       
;

class CPU

public:
    CPU()
    
        cout << "CPU()" << endl;
    
    ~CPU()
    
        cout << "~CPU()" << endl;
        
;

class MainBoard

public:
    MainBoard()
    
        cout << "MainBoard()" << endl;
    
    ~MainBoard()
    
        cout << "~MainBoard()" << endl;
        
;

class Computer

    Memory mMem;
    Disk mDisk;
    CPU mCPU;
    MainBoard mMainBoard;
public:
    Computer()
    
        cout << "Computer()" << endl;
    
    void power()
    
        cout << "power()" << endl;
    
    void reset()
    
        cout << "reset()" << endl;
    
    ~Computer()
    
        cout << "~Computer()" << endl;
    
;

int main()
   
    Computer c;

    return 0;

从该段代码可以看出,电脑的每一个部分都是独立的,但是在创建电脑的类时对每个部分进行了调用,期待的输出是其它类的对象作为电脑类的成员使用
结果输出如下
技术图片
组合关系的特点
1.将其它类的对象作为当前类的成员使用
2.当前类的对象与成员对象的生命周期相同
3.成员对象在用法上与普通对象完全一致

B.继承关系:父子关系
技术图片
面向对象中的继承指类之间的父子关系
1.子类拥有父类的所有属性和行为
2.子类就是一种特殊的父类
3.子类对象可以当作父类对象使用
4.子类中可以添加父类没有的方法和属性
继承关系的代码描述

#include <iostream>
#include <string>

using namespace std;

class Memory

public:
    Memory()
    
        cout << "Memory()" << endl;
    
    ~Memory()
    
        cout << "~Memory()" << endl;
    
;

class Disk

public:
    Disk()
    
        cout << "Disk()" << endl;
    
    ~Disk()
    
        cout << "~Disk()" << endl;
       
;

class CPU

public:
    CPU()
    
        cout << "CPU()" << endl;
    
    ~CPU()
    
        cout << "~CPU()" << endl;
        
;

class MainBoard

public:
    MainBoard()
    
        cout << "MainBoard()" << endl;
    
    ~MainBoard()
    
        cout << "~MainBoard()" << endl;
        
;

class Computer

    Memory mMem;
    Disk mDisk;
    CPU mCPU;
    MainBoard mMainBoard;
public:
    Computer()
    
        cout << "Computer()" << endl;
    
    void power()
    
        cout << "power()" << endl;
    
    void reset()
    
        cout << "reset()" << endl;
    
    ~Computer()
    
        cout << "~Computer()" << endl;
    
;

int main()
   
    Computer c;

    return 0;

运行结果
技术图片
由运行的结果可以发现在子类中没有定义 成员函数void method(),但是输出的结果中却有mv的值,这是因为继承关系的优点--子类拥有父类的所有属性和行为
同时须知道--子类就是一个特殊的父类,子类对象可以直接初始化父类对象,子类对象可以直接赋值给父类对象
继承的意义--继承是C++中代码复用的重要手段。通过继承,可以获得父类的所有功能,并且可以在子类中重写已有功能,或者添加新功能

二.继承中的访问级别

Q:子类是否可以直接访问父类的私有成员?
技术图片
代码验证


#include <iostream>
#include <string>

using namespace std;

class Parent

private:
    int mv;
public:
    Parent()
    
        mv = 100;
    

    int value()
    
        return mv;
    
;

class Child : public Parent

public:
    int addValue(int v)
    
        mv = mv + v;   
    
;

int main()
   
    return 0;

根据上面的继承关系--子类拥有父类的所有属性和行为,我们可以期待在子类的 int addValue(int v)的成员函数中对父类的私有成员变量mv进行改动
运行结果
技术图片
从运行的结果我们可以得知,子类的int addValue(int v)成员函数出错,提示mv是父类私有成员变量,不能对其进行访问,这与我们期待的结果不一样,所以在子类对父类的修饰的私有成员进行访问有了一种新的访问级别--protected
继承中的访问级别
1.面向对象中的访问级别不只是public和private
2.可以定义protected访问级别
3.关键字protected的意义--修饰的成员不能被外界直接访问,修饰的成员可以被子类直接访问
代码示例--protected的运用

#include <iostream>
#include <string>

using namespace std;

class Parent

protected:
    int mv;
public:
    Parent()
    
        mv = 100;
    

    int value()
    
        return mv;
    
;

class Child : public Parent

public:
    int addValue(int v)
    
        mv = mv + v;    
    
;

int main()
   
    Parent p;

    cout << "p.mv = " << p.value() << endl;

    // p.mv = 1000;    // error

    Child c;

    cout << "c.mv = " << c.value() << endl;

    c.addValue(50);

    cout << "c.mv = " << c.value() << endl;

    // c.mv = 10000;  // error

    return 0;

运行结果
技术图片
但是当我们在int main中对mv进行修改时得到的运行结果
技术图片技术图片
可以看到在子类的外部不允许对父类的私有成员变量进行修改
由以上的两个实例我们可以一张图片来完全表示继承关系
技术图片
小结
1.面向对象的访问级不只是public和private
2.protected修饰的成员不能被外界所访问
3.protected使得子类能够访问父类的成员
4.protected关键字是为了继承而专门设计的
5.没有protected就无法完成真正意义上的代码复用

三.C++中支持三种不同的继承方式
1.public继承--父类成员在子类中保持原有访问级别
2.private继承--父类成员在子类中变私有成员
3.protected继承--父类中的公有成员变为保护成员,其它成员保持不变

技术图片

以上是关于C++中设计三种不同继承方式的意义的主要内容,如果未能解决你的问题,请参考以下文章

c++继承是如何工作的?

C++--继承的概念和意义继承中的访问级别不同的继承方式

C++三种继承方式

初识C++继承

子类继承基类的三种继承方式

求解 c++中三种继承方式的区别!