zoukankan      html  css  js  c++  java
  • C++语言基础(9)-继承

    一.继承的基本语法

    #include<iostream>
    using namespace std;
    
    //基类 Pelple
    class People{
    public:
        void setname(char *name);
        void setage(int age);
        char *getname();
        int getage();
    private:
        char *m_name;
        int m_age;
    };
    void People::setname(char *name){ m_name = name; }
    void People::setage(int age){ m_age = age; }
    char* People::getname(){ return m_name; }
    int People::getage(){ return m_age;}
    
    //派生类 Student
    class Student: public People{
    public:
        void setscore(float score);
        float getscore();
    private:
        float m_score;
    };
    void Student::setscore(float score){ m_score = score; }
    float Student::getscore(){ return m_score; }
    
    int main(){
        Student stu;
        stu.setname("小明");
        stu.setage(16);
        stu.setscore(95.5f);
        cout<<stu.getname()<<"的年龄是 "<<stu.getage()<<",成绩是 "<<stu.getscore()<<endl;
    
        return 0;
    }

    继承的基本语法为:

    class 派生类名:[继承方式] 基类名{
        派生类新增加的成员
    };

    在本例中,class 后面的“Student”是新声明的子类,冒号后面的“People”是已经存在的基类。在“People”之前有一关键宇 public,用来表示是公有继承。继承方式包括 public(公有的)、private(私有的)和 protected(受保护的),此项是可选的,如果不写,那么默认为 private。

    二.继承权限和继承方式

    public、protected、private 指定继承方式

    不同的继承方式会影响基类成员在派生类中的访问权限。

    1) public继承方式

    • 基类中所有 public 成员在派生类中为 public 属性;
    • 基类中所有 protected 成员在派生类中为 protected 属性;
    • 基类中所有 private 成员在派生类中不能使用。


    2) protected继承方式

    • 基类中的所有 public 成员在派生类中为 protected 属性;
    • 基类中的所有 protected 成员在派生类中为 protected 属性;
    • 基类中的所有 private 成员在派生类中不能使用。


    3) private继承方式

      • 基类中的所有 public 成员在派生类中均为 private 属性;
      • 基类中的所有 protected 成员在派生类中均为 private 属性;
      • 基类中的所有 private 成员在派生类中不能使用。

    例:

    #include<iostream>
    using namespace std;
    
    //基类People
    class People{
    public:
        void setname(char *name);
        void setage(int age);
        void sethobby(char *hobby);
        char *gethobby();
    protected:
        char *m_name;
        int m_age;
    private:
        char *m_hobby;
    };
    void People::setname(char *name){ m_name = name; }
    void People::setage(int age){ m_age = age; }
    void People::sethobby(char *hobby){ m_hobby = hobby; }
    char *People::gethobby(){ return m_hobby; }
    
    //派生类Student
    class Student: public People{
    public:
        void setscore(float score);
    protected:
        float m_score;
    };
    void Student::setscore(float score){ m_score = score; }
    
    //派生类Pupil
    class Pupil: public Student{
    public:
        void setranking(int ranking);
        void display();
    private:
        int m_ranking;
    };
    void Pupil::setranking(int ranking){ m_ranking = ranking; }
    void Pupil::display(){
        cout<<m_name<<"的年龄是"<<m_age<<",考试成绩为"<<m_score<<"分,班级排名第"<<m_ranking<<",TA喜欢"<<gethobby()<<""<<endl;
    }
    
    int main(){
        Pupil pup;
        pup.setname("小明");
        pup.setage(15);
        pup.setscore(92.5f);
        pup.setranking(4);
        pup.sethobby("乒乓球");
        pup.display();
    
        return 0;
    }

     也可以使用using关键字来改变访问权限

    #include<iostream>
    using namespace std;
    //基类People
    class People{
    public:
        void show();
    protected:
        char *m_name;
        int m_age;
    };
    void People::show(){
        cout<<m_name<<"的年龄是"<<m_age<<endl;
    }
    //派生类Student
    class Student: public People{
    public:
        void learning();
    public:
        using People::m_name;  //将private改为public
        using People::m_age;  //将private改为public
        float m_score;
    private:
        using People::show;  //将public改为private
    };
    void Student::learning(){
        cout<<"我是"<<m_name<<",今年"<<m_age<<"岁,这次考了"<<m_score<<"分!"<<endl;
    }
    int main(){
        Student stu;
        stu.m_name = "小明";
        stu.m_age = 16;
        stu.m_score = 99.5f;
        stu.show();  //compile error
        stu.learning();
        return 0;
    }

     三.调用子类构造函数时必须先调用父类构造函数

    和Java中子类的构造函数初始化相似,当需要对父类的私有成员变量进行初始化时,需要调用父类的构造函数。

    例:

    #include<iostream>
    using namespace std;
    //基类People
    class People{
    protected:
        char *m_name;
        int m_age;
    public:
        People(char*, int);
    };
    People::People(char *name, int age): m_name(name), m_age(age){}
    //派生类Student
    class Student: public People{
    private:
        float m_score;
    public:
        Student(char *name, int age, float score);
        void display();
    };
    //People(name, age)就是调用基类的构造函数
    Student::Student(char *name, int age, float score): People(name, age), m_score(score){ }
    void Student::display(){
        cout<<m_name<<"的年龄是"<<m_age<<",成绩是"<<m_score<<""<<endl;
    }
    int main(){
        Student stu("小明", 16, 90.5);
        stu.display();
        return 0;
    }

    运行结果:

    小明的年龄是16,成绩是90.5。

    若不显示指明父类的构造函数,则默认调用父类的无参构造函数,例:

    #include <iostream>
    using namespace std;
    //基类People
    class People{
    public:
        People();  //基类默认构造函数
        People(char *name, int age);
    protected:
        char *m_name;
        int m_age;
    };
    People::People(): m_name("xxx"), m_age(0){ }
    People::People(char *name, int age): m_name(name), m_age(age){}
    //派生类Student
    class Student: public People{
    public:
        Student();
        Student(char*, int, float);
    public:
        void display();
    private:
        float m_score;
    };
    Student::Student(): m_score(0.0){ }  //派生类默认构造函数
    Student::Student(char *name, int age, float score): People(name, age), m_score(score){ }
    void Student::display(){
        cout<<m_name<<"的年龄是"<<m_age<<",成绩是"<<m_score<<""<<endl;
    }
    int main(){
        Student stu1;
        stu1.display();
        Student stu2("小明", 16, 90.5);
        stu2.display();
        return 0;
    }

    运行结果:

    xxx的年龄是0,成绩是0。
    小明的年龄是16,成绩是90.5。

    注意:如果将People类中的无参构造函数删除,则会发生编译错误!因为Student类的第一个构造函数没有显示的声明父类的构造函数,因此编译器就会寻找父类的无参构造函数,若发现父类没有无参构造函数,则会出现错误!

    四.子类的析构函数会优先于父类的析构函数被调用

    #include <iostream>
    using namespace std;
    class A{
    public:
        A(){cout<<"A constructor"<<endl;}
        ~A(){cout<<"A destructor"<<endl;}
    };
    class B: public A{
    public:
        B(){cout<<"B constructor"<<endl;}
        ~B(){cout<<"B destructor"<<endl;}
    };
    class C: public B{
    public:
        C(){cout<<"C constructor"<<endl;}
        ~C(){cout<<"C destructor"<<endl;}
    };
    int main(){
        C test;
        return 0;
    }

    运行结果:

     多继承下的构造函数与析构函数

    #include <iostream>
    using namespace std;
    
    //基类
    class BaseA{
    public:
        BaseA(int a, int b);
        ~BaseA();
    protected:
        int m_a;
        int m_b;
    };
    BaseA::BaseA(int a, int b): m_a(a), m_b(b){
        cout<<"BaseA constructor"<<endl;
    }
    BaseA::~BaseA(){
        cout<<"BaseA destructor"<<endl;
    }
    
    //基类
    class BaseB{
    public:
        BaseB(int c, int d);
        ~BaseB();
    protected:
        int m_c;
        int m_d;
    };
    BaseB::BaseB(int c, int d): m_c(c), m_d(d){
        cout<<"BaseB constructor"<<endl;
    }
    BaseB::~BaseB(){
        cout<<"BaseB destructor"<<endl;
    }
    
    //派生类
    class Derived: public BaseA, public BaseB{
    public:
        Derived(int a, int b, int c, int d, int e);
        ~Derived();
    public:
        void show();
    private:
        int m_e;
    };
    Derived::Derived(int a, int b, int c, int d, int e): BaseA(a, b), BaseB(c, d), m_e(e){
        cout<<"Derived constructor"<<endl;
    }
    Derived::~Derived(){
        cout<<"Derived destructor"<<endl;
    }
    void Derived::show(){
        cout<<m_a<<", "<<m_b<<", "<<m_c<<", "<<m_d<<", "<<m_e<<endl;
    }
    
    int main(){
        Derived obj(1, 2, 3, 4, 5);
        obj.show();
        return 0;
    }

    运行结果:

    BaseA constructor
    BaseB constructor
    Derived constructor
    1, 2, 3, 4, 5
    Derived destructor
    BaseB destructor
    BaseA destructor

    五.当多个父类中有同名的成员时,子类在调用时,需要在成员名字前加::

    当两个或多个基类中有同名的成员时,如果直接访问该成员,就会产生命名冲突,编译器不知道使用哪个基类的成员。这个时候需要在成员名字前面加上类名和域解析符::,以显式地指明到底使用哪个类的成员,消除二义性。

    例:

    #include <iostream>
    using namespace std;
    
    //基类
    class BaseA{
    public:
        BaseA(int a, int b);
        ~BaseA();
    public:
        void show();
    protected:
        int m_a;
        int m_b;
    };
    BaseA::BaseA(int a, int b): m_a(a), m_b(b){
        cout<<"BaseA constructor"<<endl;
    }
    BaseA::~BaseA(){
        cout<<"BaseA destructor"<<endl;
    }
    void BaseA::show(){
        cout<<"m_a = "<<m_a<<endl;
        cout<<"m_b = "<<m_b<<endl;
    }
    
    //基类
    class BaseB{
    public:
        BaseB(int c, int d);
        ~BaseB();
        void show();
    protected:
        int m_c;
        int m_d;
    };
    BaseB::BaseB(int c, int d): m_c(c), m_d(d){
        cout<<"BaseB constructor"<<endl;
    }
    BaseB::~BaseB(){
        cout<<"BaseB destructor"<<endl;
    }
    void BaseB::show(){
        cout<<"m_c = "<<m_c<<endl;
        cout<<"m_d = "<<m_d<<endl;
    }
    
    //派生类
    class Derived: public BaseA, public BaseB{
    public:
        Derived(int a, int b, int c, int d, int e);
        ~Derived();
    public:
        void display();
    private:
        int m_e;
    };
    Derived::Derived(int a, int b, int c, int d, int e): BaseA(a, b), BaseB(c, d), m_e(e){
        cout<<"Derived constructor"<<endl;
    }
    Derived::~Derived(){
        cout<<"Derived destructor"<<endl;
    }
    void Derived::display(){
        BaseA::show();  //调用BaseA类的show()函数
        BaseB::show();  //调用BaseB类的show()函数
        cout<<"m_e = "<<m_e<<endl;
    }
    
    int main(){
        Derived obj(1, 2, 3, 4, 5);
        obj.display();
        return 0;
    }

    运行结果:

  • 相关阅读:
    Vuex之state、mapState、...mapState、getters、mapGetters、...mapGetters
    Vuex之store的使用
    vue-router的使用
    Flutter之用SharedPreferences实现本地存储
    Flutter之闪屏页的开发
    Flutter之打乱对象数组
    Flutter之解决页面底部黄色条纹的方法
    Vue条件渲染方式的使用
    vue-i18n实现国际化的语言切换用法
    解决v-for报错的方法
  • 原文地址:https://www.cnblogs.com/yongdaimi/p/7079272.html
Copyright © 2011-2022 走看看