关于c++:细数继承与派生纯干货推荐10

7次阅读

共计 8455 个字符,预计需要花费 22 分钟才能阅读完成。

目录

    • 一、类与对象的根底
      • 1、简略概念
      • 2、类的类型
        • ①、私有
        • ②、公有
        • ③、爱护
      • 4、扩大:(类和构造体的区别)
    • 二、应用类和对象
      • 办法一:
      • 办法二:
      • 办法三:
    • 三、继承与派生
      • 1、名称解释
      • 2、繁多继承
        • ①、私有继承
        • ②、公有继承
        • ③、爱护继承
        • ④、总结
      • 3、多重继承
      • 4、注意事项
        • ①、互相赋值
        • ②、防止二义性

最近在学习 C ++ 面向对象设计,看似很根底的内容实际上有多知识点值得斟酌。

学完类与对象,就很想写点货色来输入我的思考和学习的想法,也心愿各位朋友一起多多交换,如果文章里有谬误的中央请多多斧正。

一、类与对象的根底

前言:

学习 C,要有面向过程的设计思维。

学习 C ++,要有面向对象的设计思维。

1、简略概念

对象: 任何一个事物都能够看成一个对象,比方一个班级,一个学校,一篇文章等等。

对象蕴含两个因素:属性 行为

举个栗子:咱们把一个班级看做一个对象,那么班级里的人数,业余,均匀问题叫做属性(动态的 )。班级上课,加入运动会等叫做行为( 动静的)。一个对象个别是由一组属性和一组行为形成。

封装:个别对象里的内容会波及到机密,在面对外人时。咱们能够把对象里的局部内容盖起来不让外人看到。

举个栗子:班级期末考试,家长想晓得班级里所有人的问题(家长对班级这个对象进行拜访 / 调用),但咱们只通知家长班级均匀问题,所有的同学的问题都不对外颁布(集体问题进行封装)。相同,平均分就是属于大家都能看到 / 接触 / 调用的内容。

2、类的类型

①、私有

听名字就晓得,这是个大家都能看失去或者接触失去的内容。

比方上个栗子中的班级平均分就属于私有局部,班级中的每位家长都能够看到。

`class Student
{public:
}` 

②、公有

听名字就晓得属于定义对象所领有的局部,不能让外界看到或者解除(当然也会有例外,这里挖个坑)。把局部成员进行封装,避免外人看到。

上个栗子中对应的是班级里每位同学的问题。

`class Student
{private:
}` 

③、爱护

首先一个问题,爱护类型和公有类型有什么区别?这里咱们先做个简略的介绍:

公有和爱护的成员函数和数据只能被本类中的其余成员函数所调用,而不能被类外调用。而爱护的性能在 继承与派生 中更能体现进去,当然也有例外的状况产生。同公有类型一样,挖个坑。写完例外情况(友元),我会在此处做个文章链接。

`class Student
{protected:
}` 

4、扩大:(类和构造体的区别)

先上两种定义:(Student 为例)

`///class
class Student
{
    private:
        int num;
        char sex:
        string name;
    public:
        void display();};` 
`///struct(C)struct Student
{
        int num;
        char sex:
        string name;    
}stu;

void display(int num,char sex,string name);` 

补充一个小常识:C++ 在设计的时候就以兼容 C,但又不是齐全简略的继承 C,同时还要有本人的特点为准则进行开发。

最显著的就是 struct 中没有 private 和 public,想给 student 增加什么属性间接写进去就完事了。

class 不同,除了想把属性加进去外,还要思考这个属性要不要让他人看到。想让他人能看到,退出 public 中。不想让他人看到就退出 private 中。

举个栗子:如果把 struct 比作一家新百伦鞋店,那么这家店就属于通透型的,穿鞋换鞋坐在沙发板凳上就能够实现,无需试衣间。所有的中央和盘托出。class 更像是含有试衣间的优衣库。筛选衣服的时候大家都能看到,然而试衣服的时候就必须要去试衣间里。我想没有多少人在换衣服的时候被他人看到吧?

以上内容援用于比拟 C 中的 struct 和 C ++ 中的 class。

而在 C ++ 中对于 struct 的用法进行了降级:

`///struct(C++)struct Student
{
    private:
        int num;
        char sex:
        string name;
    public:
        void display();};` 

可见 C ++ 中应用 struct 也能够像 class 一样对成员进行 public 或 private 分类。

此时他们的区别就是对于未声明的成员进行默认分类。

`///class 
class Student
{
        int num;
        char sex:
        string name;
        /// 三种成员被默认为 private 类型
        /// 进行类内拜访,类外不能拜访
};` 
`///struct(C++)struct Student
{
        int num;
        char sex:
        string name;
        /// 三种成员默认为 public 类型
        /// 类内类外均能够拜访
};` 

二、应用类和对象

设计好了咱们所须要的类,接下来就是定义对象。

办法一:

`class Student stu1,stu2;///class Student 合起来作为一个整体类名,来定义对象

Student stu1,stu2;/// 或者间接应用 Student 定义对象,与构造体定义对象雷同 ` 

办法二:

`class Student
{
    private:
        int num;
        char sex:
        string name;
    public:
        void display();}stu1,stu2;                    /// 与构造体定义雷同 ` 

办法三:

`class 
{
    private:
        int num;
        char sex:
        string name;
    public:
        void display();        /// 这能够不通过类名间接定义对象,然而不举荐应用。构造体中也是这样}` 

三、继承与派生

1、名称解释

构造函数

咱们通过构造函数来使对象的属性进行初始化。如果想增加初始值,能够手动设置。反之能够交给编译器主动指定默认值。建设好类之后,个别咱们须要对其进行初始化。这是为什么呢?就像咱们注册某个网站时,填写好注册名称,明码进行默认抉择一样。在登录之后会要求进行批改明码以保障登录的私密性。

析构函数

如果说构造函数是为了不便用户对类进行初始化。那么析构函数就是在你实现所有程序性能,帮你进行收尾后勤工作。此时你不必管设置了多少个属性,开拓了多少内存空间。只有析构函数执行,就能帮你实现所有。我更违心称之为妈妈式的程序。

继承

聊下继承(inheritance),这个单词也有遗传的意思。那么就看进去继承或遗传的货色有前辈的内容,也会有本人独有 / 新增加的内容。

派生

在原来曾经存在的类的根底上建设一个新的类。这个过程叫做父类派生出子类。子类继承了父类的成员内容,也会存在着属于本人新增加的成员内容。

基类

又名:父类。曾经存在设计好的类型。(与上面的派生类做对应记忆)

派生类

又名:子类。通过继承之前设计好的类,失去新建设的类。

2、繁多继承

派生类中的成员包含了从基类继承过去的成员和本人新减少的成员两局部。

①、私有继承

对基类成员内容通过私有形式继承失去的派生类。

`/// 基类
class Student
{   int num;                        // 默认为 private 类型
    char name[30];
    char sex;
 public:                             
   void display( )                    // 对成员函数 display 的定义 {cout<<"num:"<<num<<endl;
     cout<<"name:"<<name<<endl;
     cout<<"sex:"<<sex<<endl; } 
};` 
`/// 派生类
class Student1: public Student// 申明基类是 Student
{
private:
    int age;    // 新减少的数据成员
    string addr;  // 新减少的数据成员
public:
   void display_1( )  // 新减少的成员函数 {  
       cout<<"age:"<<age<<endl; 
       cout<<"address:"<<addr<<endl;
    }   
};` 

补充: 在建设派生类的过程中,基类不会做任何扭转。派生类除了从基类中失去成员内容,也能够从新定义属于本人的变量与函数。

例如:父类对象为“马”,含有的成员变量有马的性别,年龄等。咱们能够对马进行更加粗疏的划分,建设派生类汗血宝马(增加新的成员变量:跑步里程),蒙古马(增加新的成员变量:毛发长度),大宛马(增加新的成员变量:一顿能吃多少个馒头)等等。这样就就与派生类就与基类有了别离。

那么通过私有继承的形式,能够从派生类中拜访基类的内容吗?当你脑海中蹦出这个问题时就阐明曾经学会触类旁通了。

私有派生时,基类中的所有成员在派生类中的放弃各个成员的拜访权下,如下图 另外上个图能让大家更好了解

上述图片中(a)为基类(父类),(b)为派生类(子类),(c)是整顿过后的派生类。能够看出通过私有继承图(c)中曾经没有了类 A 的 private 变量 k。这是因为通过私有继承,对父类的公有变量曾经进行了封装,无奈在派生类中拜访(不可见)。然而能够通过类 A 中的成员函数援用到 private 中的 k。

通过私有继承中,派生类想对基类中的 private 成员不能够援用,那咱们就是想援用怎么办?

这里就是后面说的特例——友元。挖个坑!!!

上面是个私有继承的小实例,有工夫的读者能够认真看一下,代码很简略。

`#include <bits/stdc++.h>

using namespace std;

class Student
{   int num = 12138;                        // 默认为 private 类型
    char name[30] = "ZhangSan" ;
    char sex = 'M';
 public:
   void display( )                    // 对成员函数 display 的定义 {cout<<"num:"<<num<<endl;
     cout<<"name:"<<name<<endl;
     cout<<"sex:"<<sex<<endl; }
};

class Student1: public Student// 申明基类是 Student
{private:
    int age = 18;    // 新减少的数据成员
    string addr = "China";  // 新减少的数据成员
public:
   void display_1( )  // 新减少的成员函数 {      
           cout<<"age:"<<age<<endl;
        cout<<"address:"<<addr<<endl;
    }
};
///ac 不知深
int main() {
    Student stu1;
    Student1 stu2;
    cout << "stu1 间接输入" << endl;
    stu1.display();
    cout << "stu2 间接输入" << endl;
    stu2.display_1();
    cout << "stu1 通过拜访 stu1 输入" << endl;
    stu2.display();
    return 0;
}` 

②、公有继承

对基类成员内容通过公有形式继承失去的派生类。基类中 public 成员和 protected 成员会在派生类中都变成公有的。然而在派生类中依然能够间接应用这些成员。基类中的 private 成员在派生类中仍然不能间接应用。

`/// 基类
class Student
{   int num;                        // 默认为 private 类型
    char name[30];
    char sex;
 public:                             
   void display( )                    // 对成员函数 display 的定义 {
        cout<<"num:"<<num<<endl;
         cout<<"name:"<<name<<endl;
         cout<<"sex:"<<sex<<endl; 
     } 
};` 
`/// 派生类
class Student1: private Student// 申明基类是 Student
{
private:
    int age;    // 新减少的数据成员
    string addr;  // 新减少的数据成员
public:
   void display_1( )  // 新减少的成员函数 {  
           cout<<"age:"<<age<<endl; // 援用派生类的公有成员
           cout<<"address:"<<addr<<endl;    // 援用派生类的公有成员
    }   
    
    void get_value_1() {cin >> num >> name >> sex ;        // 输出派生类数据}
};` 

和私有继承是的原理都是类似的。

公有派生时,基类中的所有成员在派生类中的放弃各个成员的拜访权下,如下图 同样上个图让大家印象更粗浅 上述图片中(a)为基类(父类),(b)为派生类(子类),(c)是整顿过后的派生类。能够看出通过公有继承图(c)中曾经没有了类 A 的 private 变量 k。这是因为通过公有继承,对父类的公有变量曾经进行了封装,无奈在派生类中拜访(不可见)。同时,类 A 中的 public 与 protected 类型均转变为类 B 的 private 类型。

由此咱们能够看到,公有继承仿佛更王道些。对于基类继承来的成员,派生类外是都不能够拜访的。这种继承形式更偏向于爱护隐衷内容,不想让其余程序员晓得咱们本人定义的内容。

上面这个实战小例子,通过公有继承,能够很好与私有继承实例做个比拟——无奈通过类外拜访公有继承的成员函数。

`#include <bits/stdc++.h>

using namespace std;

class Student
{   int num = 12138;                        // 默认为 private 类型
    char name[30] = "ZhangSan" ;
    char sex = 'M';
 public:
    void display( )                    // 对成员函数 display 的定义 {cout<<"num:"<<num<<endl;
     cout<<"name:"<<name<<endl;
     cout<<"sex:"<<sex<<endl; }
};

class Student1: private Student// 申明基类是 Student
{private:
    int age = 18;    // 新减少的数据成员
    string addr = "China";  // 新减少的数据成员
public:
   void display_1( )  // 新减少的成员函数 {    cout<<"age:"<<age<<endl;
        cout<<"address:"<<addr<<endl;
    }
};
///ac 不知深
int main() {
    Student stu1;
    Student1 stu2;
    cout << "stu1 间接输入" << endl;
    stu1.display();     /// 能够通过 stu1 间接拜访基类
    cout << "stu2 间接输入" << endl;
    stu2.display_1();   /// 能够通过 stu2 间接拜访派生类
    ///cout << "stu1 通过拜访 stu1 输入" << endl;
    ///stu2.display();     // 本语句谬误,无奈通过 stu2 拜访基类函数
    return 0;
}` 

③、爱护继承

爱护成员和公有成员在基类外都是不能被拜访的,能够认为爱护成员对类来说是公有的。然而爱护成员能够被派生类的成员函数援用。这是两者比拟显著的区别。大家看到这个图肯定感觉很蛊惑,这个图明明和公有继承是一样的啊?

没错,然而 protected 成员是一种具备血缘关系内外有别的成员。它对派生类的对象而言,是公开成员,能够拜访,对血统内部而言,与公有成员一样被荫蔽。但事无相对,这里再一次挖个坑——友元。

在举个栗子,private 更像是你们家的存折户口本房产证等,个别都由父母(父类能够拜访)放在比拟荫蔽的中央。即便是作为孩子的你(派生类)也不晓得(无法访问),更不用说你的街坊敌人(类外无法访问)了。protected 更像是你父母抽屉里的指甲剪,父母(父类能够拜访)晓得在哪,你也晓得在哪(派生类能够拜访)。然而敌人街坊(类外无法访问)就不晓得在哪里。

还是迷迷糊糊的敌人间接看上面一张图!!!上面一张图给你解释分明!!!类 A 别离通过 private 和 protected 继承失去 B 和 C,再同时 public 继承失去 B1 和 C1。这个时候公有继承和私有继承的区别就显现出来了:

B1 无法访问 A 中的 public 与 protected 成员;

C1 能够拜访 A 中的 public 与 protected 成员

接下来简略做个总结比拟:

来个实战小例子

`#include <bits/stdc++.h>

using namespace std;

class Student
{
protected:
    int num;
    char name[30];
    char sex;
 public:
                            /// 基类无专用成员
};

class Student1: protected Student// 申明基类是 Student
{private:
    int age;    // 新减少的数据成员
    string addr;  // 新减少的数据成员
public:
    void get_value1() {
        cin >> num >> name >> sex;      // 输出爱护基类数据成员
        cin >> age >> addr;             // 输出派生类数据成员
    }

    void display_1( )  // 新减少的成员函数 {
        cout<<"num:"<<num<<endl;       // 援用基类的爱护成员
         cout<<"name:"<<name<<endl;     // 援用基类的爱护成员
         cout<<"sex:"<<sex<<endl;       // 援用基类的爱护成员
        cout<<"age:"<<age<<endl;       // 援用派生类的公有成员
        cout<<"address:"<<addr<<endl;  // 援用派生类的公有成员
    }
};
///ac 不知深
int main() {
    Student1 stu1;      //stu1 是派生类 Student1 类的对象
    stu1.get_value1();  //get_value1 是派生类中的私有成员函数,输出数据
    stu1.display_1();   //display1 是派生类中的私有成员函数,输入数据
    return 0;
}` 

④、总结

最初咱们做一个基类成员在派生类中的拜访属性比拟

派生类中的拜访属性有四种:不可拜访publicprivateprotected

①不可拜访,派生类内类外都不能拜访;

②public,派生类内类外都能够拜访;

③private,派生类内能够拜访,派生类外不能拜访;

④protected,派生类内能够拜访,派生类外不能拜访,其新派生出的下一代的派生类能够拜访。

3、多重继承

后面探讨的是繁多继承。实际上,经常有一个派生类有两个或多个基类,派生类从两个或多个基类中继承所需的属性。比方,你的白天在公司扮演者普普通通的码农,早晨扮演着媳妇的好老公。你的身份就可能须要继承多个基类能力更好更欠缺的刻画出你的形象。代码更好的向前一步倒退,咱们须要多重继承。

这里我感觉没有太多难点,只有繁多继承弄明确了多重继承分分钟就 ok!

`class  D: public  A, protected B, private C 
{....// 派生类中新减少成员};` 

这里就间接给大家一个简略的例子进行学习

`class  A
{
public:    
    int x;
    void Show(){cout <<"x="<<x<<'n';}
};

class B
{
public:    
    int y;
    void Show(){cout <<"y="<<y<<'n';}
};

class C:public A,public B
{
    public:    
        int y; // 类 B 和类 C 均有 y 的成员
};

void  main(void) {      
    C c1;               
    c1.x=100;
    c1.y=200;    // 给派生类中的 y 赋值
    c1.B::y=300;    // 给基类 B 中的 y 赋值
    c1.A::Show();        
    c1.B::Show();    // 用作用域运算符限定调用的函数
    cout <<"y="<<c1.y<<'n';    // 输入派生类中的 y 值
    cout <<"y="<<c1.B::y<<'n';    // 输入基类 B 中的 y 值
}` 

4、注意事项

①、互相赋值

这里其实真正的叫法是基类与派生类的转换。这个篇幅太长(次要是我懒),咱们放在下篇文章持续更新!

②、防止二义性

多种继承可能更好地解决比较复杂的问题。比方一个退职的研究生老师张三,张三属于老师类,属于研究生类,也属于一个人类(废话 hhhh),咱们做个简略的定义。

`class Teacher       // 老师    
{
public:
    void display();
protected:
    string name;    // 姓名
    int age;        // 年龄
    string title;   // 职务
    
};

class Student
{
public:
    void display1();
protected:
    string name;    // 年龄
    char sex;       // 性别
    float score;    // 分数
};

class Graduate:public Teacher,public Student
{
public:
    void show();
private:
    float wage;     // 补贴
};
///ac 不知深 ` 

这里咱们看到在类 Teacher 和类 Student 中都有姓名成员,如果只是单纯的继承会导致 Graduate 中存在两个 name 函数,初始化赋值时肯定会报错。具体怎么解决这个问题,麻烦各位读者点赞和关注,我会尽快更新这部分的常识并在上面放上链接!

本文转自:SDK 社区(sdk.cn)是一个中立的社区,这里有多样的前端常识,有丰盛的 api,有爱学习的人工智能开发者,有有趣风趣的开发者带你学 python,还有将来炽热的鸿蒙,当各种元素组合在一起,让咱们一起脑洞大开独特打造业余、好玩、有价值的开发者社区,帮忙开发者实现自我价值!

正文完
 0