【C++课程学习10】继承

参考

  • 范磊C++(第12课时)

笔记

继承和派生的基本概念

  • 什么是继承和派生

在这里插入图片描述

在这里插入图片描述

  • 复杂的继承和派生

在这里插入图片描述

  • 继承和派生如何在C++中实现?
    在这里插入图片描述

在这里插入图片描述

派生类型(派生权限)的概念,以后会讲到。

单一继承

只有一个基类

#include <iostream>
using namespace std;
class Father
{
private:
    int fatherHight,fatherWeight;
public://构造函数只有一个参数,与下面的对应!
    void setFatherHight(int x){fatherHight=x;}
    void setFatherWeight(int x){fatherWeight=x;}
    void getFatherHightAndWeight(){cout<<"身高为"<<fatherHight<<endl;
        cout<<"体重为"<<fatherWeight<<endl;}

};

class Son :public Father
{
private:
    int sonWidth,sonLong;
public:
    void setSonHWidth(int x){sonWidth=x;}
    void setSonWLong(int x){sonLong=x;}
    void getsonHightAndWeight(){cout<<"肩宽为"<<sonWidth<<endl;
        cout<<"臂长为"<<sonLong<<endl;}


};

int main(int argc, const char * argv[]) {
    Son LiMing;
    LiMing.setFatherHight(180);
    LiMing.setFatherWeight(80);
    LiMing.setSonWLong(134);
    LiMing.setSonHWidth(65);
    LiMing.getsonHightAndWeight();
    LiMing.getFatherHightAndWeight();
    return 0;
}

输出结果:

在这里插入图片描述

保护成员

在这里插入图片描述

#include <iostream>
using namespace std;
class Father
{
//private://子类不能访问
protected://只能子类来访问
    int fatherHight,fatherWeight;
public://构造函数只有一个参数,与下面的对应!
    void setFatherHight(int x){fatherHight=x;}
    void setFatherWeight(int x){fatherWeight=x;}
    //void getFatherHightAndWeight(){cout<<"身高为"<<fatherHight<<endl;
      //  cout<<"体重为"<<fatherWeight<<endl;}

};

class Son :public Father
{
private:
    int sonWidth,sonLong;
public:
    void setSonHWidth(int x){sonWidth=x;}
    void setSonWLong(int x){sonLong=x;}
    //void getsonHightAndWeight(){cout<<"肩宽为"<<sonWidth<<endl;
      //  cout<<"臂长为"<<sonLong<<endl;}
    void PrintAll(){
        cout<<"肩宽为"<<sonWidth<<endl;
        cout<<"臂长为"<<sonLong<<endl;
        cout<<"身高为"<<fatherHight<<endl;
        cout<<"体重为"<<fatherWeight<<endl;
    }


};

int main(int argc, const char * argv[]) {
    Son LiMing;
    LiMing.setFatherHight(180);
    LiMing.setFatherWeight(80);
    LiMing.setSonWLong(134);
    LiMing.setSonHWidth(65);
    //LiMing.getsonHightAndWeight();
    //LiMing.getFatherHightAndWeight();
    LiMing.PrintAll();
    return 0;
}

输出结果:
在这里插入图片描述

共有派生

  • 共有
    在这里插入图片描述

  • 保护
    在这里插入图片描述

  • 私有
    在这里插入图片描述

继承的赋值

在这里插入图片描述

子类可以赋值给父类,但父类不能给子类。
因为父类的成员数少。
同样,基类的指针可以指向派生类对象,但是派生类指针不能指向基类对象。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

私有派生(继承)

在这里插入图片描述

#include <iostream>
using namespace std;
class Father
{
public:
    void room(){cout<<"父亲的大房子我可以享受"<<endl;}
};//注意分号

class Son: private Father
{
public:
    void enjoy(){room();}
};

int main(int argc, const char * argv[]) {
    Son a;
    a.enjoy();
    return 0;
}

输出结果:

在这里插入图片描述

在这里插入图片描述

多重继承

在这里插入图片描述

#include <iostream>
using namespace std;
class Father
{
public:
    void setA(int a ){tall=a;}
    void print1(){cout<<"身高的值:"<<tall<<endl;}
private:
    int tall;
};

class Mother
{
public:
    void setB(int a ){weight=a;}
    void print2(){cout<<"体重的值:"<<weight<<endl;}//成员函数名字最好不要相同,否则会报错!
private:
    int weight;
};

class Son: public Father,public Mother
{
public:
    void setC(int a ){age=a;}
    void print3(){print1();print2();cout<<"年龄的值:"<<age<<endl;}
private:
    int age;
};

int main(int argc, const char * argv[]) {
    Son Mike;
    Mike.setA(175);
    Mike.setB(80);
    Mike.setC(25);
    Mike.print3();
    return 0;
}

输出:

在这里插入图片描述

当然同样的也可以设置派生权限。

继承的构造与构析

构造函数和析构函数的执行顺序。
在这里插入图片描述

在这里插入图片描述

基类的构造顺序是按继承时的给定顺序执行。
析构时则正好相反。
在这里插入图片描述

向基类构造函数传递参数

在这里插入图片描述

在这里插入图片描述

  • 方法1
    方法正确,但是调用父类的构造函数对创建子类对象没有帮助,( 无用的构造函数)这相当于浪费了系统的开销。
#include <iostream>
#include<string>
using namespace std;
class Father
{
public:
    Father(){cout<<"构造基类对象"<<endl;}
    ~Father(){cout<<"析构基类对象"<<endl;}
    void setA(int a ){tall=a;}
    void print(){cout<<name<<"身高的值:"<<tall<<"cm"<<endl;}
protected:
    string name;
    int tall;
private:

};

class Son :public Father
{
public:
    Son(string a, int i, int j){
        name=a;
        tall=i;
        weight=j;
        cout<<"构造子类对象"<<endl;}
    ~Son(){cout<<"析构子类对象"<<endl;}
    void setA(int a ){tall=a;}
    void print1(){print();cout<<"体重的值:"<<weight<<"kg"<<endl;}//不能覆盖掉父类的,因此要改名。
protected:
    int weight;
private:
};

int main(int argc, const char * argv[]) {
    Son Mike("Mike",180,80);
    Mike.print1();
    cout<<"程序结束"<<endl;
    return 0;
}

输出:
在这里插入图片描述

  • 方法2
    充分利用基类的构造函数。
#include <iostream>
#include<string>
using namespace std;
class Father
{
public:
    //Father(){cout<<"构造基类对象"<<endl;}
    Father(string a, int i){
        name=a;
        tall=i;
        cout<<"构造带两个参数的基类对象"<<endl;}
    ~Father(){cout<<"析构基类对象"<<endl;}
    void setA(int a ){tall=a;}
    void print(){cout<<name<<"身高的值:"<<tall<<"cm"<<endl;}
protected:
    string name;
    int tall;
private:

};

class Son :public Father
{
public:
    Son(string a, int i, int j):Father(a,i){
        weight=j;
        cout<<"构造子类对象"<<endl;}
    ~Son(){cout<<"析构子类对象"<<endl;}
    void setA(int a ){tall=a;}
    void print1(){print();cout<<"体重的值:"<<weight<<"kg"<<endl;}//不能覆盖掉父类的,因此要改名。
protected:
    int weight;
private:
};

int main(int argc, const char * argv[]) {
    Son Mike("Mike",180,80);//
    Mike.print1();
    cout<<"程序结束"<<endl;
    return 0;
}

输出:

在这里插入图片描述

在这里插入图片描述

多重继承容易产生两义性

成员重名导致的问题。
会产生警告⚠️
强行运行的话,就会产生覆盖问题。
可以使用作用域操作符来避免这个问题。

两义性的归属问题

在这里插入图片描述

继承中的重载

在这里插入图片描述

一旦子类定义了构造函数,基类中的构造函数就会被覆盖。
【问题】const函数,只能由const对象调用吗???

原文地址:https://www.cnblogs.com/vrijheid/p/14223012.html