精华内容
下载资源
问答
  • c++类的继承
    千次阅读 多人点赞
    2018-10-21 22:18:34

    C++类继承

    1.is-a继承

    1.1公有继承

    特性:

    //保持基类的访问权限不变,基类数据成员只能通过基类的方法访问
    
    //派生类需要自己的构造函数,创建对象时,需要使用成员初始化列表,将基类成员一起初始化
    
    //派生类可以重载基类成员函数,也可以添加额外的方法和数据成员
    
    //创建派生类对象时,基类对象将被先行创建,即先调用基类的构造函数
    
    //如果不调用基类构造函数,直接创建派生类对象时,将使用默认的基类构造函数
    
    //实例
    class Person{
    private:
        char m_name[10];
        char m_sex[10];
    public:
        Person(const char *name="yang",const char *sex="male"){
    		strcpy(m_name,name);
            strcpy(m_sex,sex);
            cout<<"我是基类构造函数,我被优先调用了\n";
        }
        void show() const{
    		cout<<m_name;
    		cout<<"\n";
    		cout<<m_sex;
            cout<<"\n";
    	}
    };
    class Student:public Person{
    private:
        char m_xuehao[10];
    public:
        Student(const char *name="xu",const char *sex="male",const char *xuehao="1510370221")
            :Person(name,sex){//使用成员初始化列表,如果省略,则默认调用Person()构造函数
    			strcpy(m_xuehao,xuehao);
            }
        void display() const{
            show();
            cout<<"\n";
            cout<<m_xuehao;
        }
    };  //注意赋值一个常量字符串给一个char *时,必须加上const,由于字符串为一个常量,不能被修改,会发出警告!!!!
    int main(){
    	Person p;
    	p.show();
        
        Student s;
        s.display();
    }//打印:  
    	/*  我是基类构造函数,我被优先调用了
    		yang
        	male
        	我是基类构造函数,我被优先调用了
    		xu
    		male
    		1510370221
    		*/
    
    //此外如果构造函数new一块内存,还需要重定义新的复制构造函数
    
    //派生类指针不能指向和引用基类,即不能讲基类放大; 但是可以使用基类指针指向和引用派生类,可以放窄
    Person p;
    Student *s=p;//error
    
    Student s;
    Person *p=s;//允许
    
    //派生类对象可以赋给基类对象,不能反转 
    Student s;
    Person p=s;//语义:Student is a person!but,person not a student.
    

    1.2私有继承

    用的少,不是重点…

    1.3保护继承

    主要用于继承中派生类可以直接访问基类的protected成员

    2.has-a关系

    //方法一:在类使用其他类对象
    class Student{
    private:
        string m_name;//使用string类对象
    public:
        Student(const string name){ ... }
        
    }
    
    //方法二:使用私有继承
    class Student:private string{//私有继承string对象
    private:
        char m_name[10];
        
    public:
        Student(const char* name="yang")
            :string(name){ ... }
    }
    

    3.多态公有继承

    3.1特性:

    • 能够在派生类中重定义基类的方法,注意不是重载,是重定义,原型不一定相同,函数体不同,将隐藏基类方法;;;重载是原型不同,函数体必须相同;;;如果基类虚函数被重载,则需在派生类重定义所有版本

    • 基类使用虚方法,在基类和派生类中不同实现

    • 编译器对非虚方法使用静态联编,是哪个数据类型调用哪个方法;使用虚方法,将动态联编,根据指针和引用对象来调用相应的方法

    • 静态联编:执行效率更高,如果类不用做基类,就不使用动态联编!!只有预期哪些将被重定义的方法声明为虚的!

    //实例
    class Person{
    private:
        char m_name[10];
        char m_sex[10];
    public:
        Person(const char *name="yang",const char *sex="male"){
    		strcpy(m_name,name);
            strcpy(m_sex,sex);
            cout<<"我是基类构造函数,我被优先调用了\n";
        }
        virtual ~Person(){}//基类使用虚析构方法,保证释放派生对象时,按照正确的顺序调用析构函数
        
       	virtual void show() const{//基类使用虚方法,方便程序根据对象就能调用相应的方法
    		cout<<m_name;
    		cout<<"\n";
    		cout<<m_sex;
            cout<<"\n";
    	}
    };
    class Student:public Person{
    private:
        char m_xuehao[10];
    public:
        Student(const char *name="xu",const char *sex="male",const char *xuehao="1510370221")
            :Person(name,sex){
    			strcpy(m_xuehao,xuehao);
            }
       virtual void display() const{//派生类加上virtual,方便识别,可以省略,最好加上
            Person::show();//显式调用基类的同名方法,作用解析符不能省略,否则将无限递归
            cout<<"\n";
            cout<<m_xuehao;
        }
    }; 
    
    int main(){
    	Student s;
        Person *p=&s;
        p->show();//由于show声明为virtual,采用动态联编根据对象调用Student::show()
    }
    

    3.2虚函数实现原理

    //使用一个指向虚函数表的指针vtbl
    
    //派生类与基类共用一个指向虚函数表的指针,如果虚函数没有被重新定义,则此虚函数地
    址不变,如    
    果改变或者添加了新的虚函数,将保存为一个新的地址!!
    
    //无论虚函数有多少个,类与实例对象都只保存一个vtbl,只是指向的虚函数表的大小不同而已!!
    
    //可见使用虚函数,将增加以下时间和空间成本
    	/*
    		1.每个对象额外增加一个vtbl内存
    		2.每个类将创建一个虚拟地址表数组
    		3.每次函数调用,需要查找地址
    	*/
    //注意几点:构造函数不能为虚,析构函数必须为虚!否则只会释放基类的new部分内存,造成内存泄漏;
    友元函数不能为虚!
    Person *p=new Student;
    ...
    delete p;//假设Student对象new一个内存,此时只会调用Person的析构函数,
    但是Student内存没有释放,而使用虚析构函数,则直接调用Student的析构函数,从而释放全部的内存!!    
    

    注:以上代码为了方便,直接定义与实现一起写了,这样会导致方法均是内联函数,非常浪费内存,所以还是将方法实现放在定义之外!!!

    4.纯虚函数和抽象基类

    //纯虚函数指在基类中没有实现代码,专门为了派生类继承重定义使用!!
    virtual void show() const=0;//纯虚函数
    
    //含有纯虚函数的类都可以叫做抽象类,专门用来被继承,重定义实现的,不能被创建实例!
    
    //好处:方便将多个派生类使用基类指针数组进行统一管理
    

    5.多继承、多重继承和虚拟继承

    //多继承,比如班长多继承Leader,Student,
    class Monitor:public Leader,public Student{
        ...
    }
    
    //多重继承,由于Leader,Student又继承与Person,导致Monitor存在Person的两份拷贝,非常浪费内存,完全没必要
    class Monitor:public Leader,public Student{
        ...
    }
    
    //使用虚拟继承
    class Leader:virtual public Person{
        ...
    }
    class Student:virtual public Person{
        ...
    }
    class Monitor:public Leader,public Student{
        ...
    }//使用虚拟继承从而解决了拷贝多基类的问题,只会保留一份拷贝
    

    6.模板类

    +补坑…

    更多相关内容
  • 主要介绍了C++类继承之子类调用父类的构造函数的实例详解的相关资料,希望通过本文大家能够掌握C++类继承的相关知识,需要的朋友可以参考下
  • C++类继承示例

    2021-01-20 03:43:16
    C++的子类与孙子都实现了虚函数时,孙子的实现会覆盖掉子类的实现。  继承的主要的应用是把不同的放到一个数组中,然后遍历调用同名函数。  实例如下: #include #include #include using ...
  • C++类继承——公有继承

    千次阅读 2020-04-22 22:32:13
    C++中的继承机制提供了较高层次的重用性。许多厂商提供了类库,类库由声明和实现构成。类继承可以从已有的中派生出新的,派生类继承了基类的数据和方法。 我们可以在派生中添加新的数据或方法,此时...

    1 C++中的继承

    • C++中的类的继承机制提供了较高层次的重用性。许多厂商提供了类库,类库由类声明和实现构成。类继承可以从已有的类中派生出新的类,派生类继承了基类的数据和方法。
    • 我们可以在派生类中添加新的类数据或类方法,此时称为公有继承。如果在派生类中修改了基类类方法的行为,那么称为多态公有继承
    • 一般情况下,我们修改基类源码就可以实现派生类。C++的继承机制甚至不需要访问基类的源码就可以派生出派生类,只需要基类的头文件和编译后的代码即可。

    1.1 公有继承

    使用公有继承,可以达到如下的特性:

    • 基类的公有成员成为派生类的公有成员,基类的私有部分也成为派生类的一部分,但只能通过基类的公有和保护方法访问。
    • 派生类需要自己的构造函数,派生类不能访问基类的私有数据,所以派生类构造函数要调用基类构造函数来初始化基类的私有数据。基类对象应在程序进入派生类构造函数前被创建,用初始化列表实现。
    • 基类指针或引用可以在不进行显式类型转换的情况下指向派生类对象,但基类指针或引用只能调用基类成员。
    • 可以将基类对象初始化为派生类对象,可以将派生类对象赋给基类对象。
    // tabtenn1.h
    #ifndef TABTENN1_H_
    #define TABTENN1_H_
    #include <string>
    using std::string;
    class TableTennisPlayer		//基类声明
    {
    private:
        string firstname;
        string lastname;
        bool hasTable;
    public:
        TableTennisPlayer (const string & fn = "none",const string & ln = "none", bool ht = false);
        void Name() const;
        bool HasTable() const { return hasTable; };
        void ResetTable(bool v) { hasTable = v; };
    };
    
    class RatedPlayer : public TableTennisPlayer	//派生类声明,公有派生
    {
    private:
        unsigned int rating;
    public:
        RatedPlayer(unsigned int r = 0, const string & fn = "none",
        			const string & ln = "none", bool ht = false);
        RatedPlayer(unsigned int r, const TableTennisPlayer & tp);
        unsigned int Rating() const { return rating; }
        void ResetRating (unsigned int r) {rating = r;}
    };
    #endif
    
    
    //tabtenn1.cpp 
    #include "tabtenn1.h"
    #include <iostream>
    TableTennisPlayer::TableTennisPlayer (const string & fn, const string & ln, bool ht) :
    									 firstname(fn),lastname(ln), hasTable(ht) {}
    void TableTennisPlayer::Name() const
    {
        std::cout << lastname << ", " << firstname;
    }
    RatedPlayer::RatedPlayer(unsigned int r, const string & fn,
         const string & ln, bool ht) : TableTennisPlayer(fn, ln, ht)//在初始化列表显式调用基类构造函数
    {
        rating = r;
    }
    RatedPlayer::RatedPlayer(unsigned int r, const TableTennisPlayer & tp)
        : TableTennisPlayer(tp), rating(r) //调用基类复制构造函数,未定义,默认隐式复制
    {
    }
    

    1.2 多态公有继承

    • 同一个方法的行为在基类和派生类中不同时,称为多态公有继承。
    • 我们要在基类声明中将基类中的那些要在派生类中重新定义的方法声明为虚的virtual,最好在派生类中也同样用关键字virtual指明,实现代码中不用加virtual。这样程序使用动态联编的技术,将根据引用类型或指针类型选择相应的方法,而非根据对象类型。
    • 基类的析构函数也要声明为虚的,这样能确保正确的析构顺序。 如果基类析构函数不是虚的,将只调用对应于指针类型的析构函数。基类析构函数是虚的,能够保证析构派生类对象时,先调用派生类析构函数,然后会自动调用基类析构函数。
    • 派生类可以直接调用基类的公有方法,但当派生类重写该函数而导致函数同名时,注意在调用基类公有方法时加上作用域解析运算符。
    • protected关键字用于对象的保护访问。protected和privated的区别只在派生类体现,派生类的成员可以直接访问基类的保护成员,但不能直接访问基类的私有成员。其他类不能访问基类的保护成员。一般我们将protected用于那些希望只被派生类访问的成员函数。
    //student.h
    #ifndef STUDENT_H
    #define STUDENT_H
    
    #include <QString>
    class cl_person     //基类
    {
    private:
        QString m_name;
        int     m_age;
    public:
        cl_person(QString name = "no_name",int age = 18);
        virtual ~cl_person() {}     //基类析构函数声明为虚的
        virtual QString getName() const {return m_name;} //派生类要重写,基类声明为虚的
        int getAge() const {return m_age;}
    };
    
    class cl_student : public cl_person     //公有派生
    {
    private:
        QString m_school;
    
    public:
        cl_student(QString name = "no_name",int age = 18,QString school = "no_school");
        ~cl_student() {}
        virtual QString getName() const;    //派生类重写的基类函数,我们也一般把它声明为虚的
    };
    #endif // STUDENT_H
    
    //student.cpp
    #include "student.h"
    cl_person::cl_person(QString name,int age)
    {
        m_name = name;
        m_age = age;
    }
    
    cl_student::cl_student(QString name,int age,QString school) : cl_person(name,age) //在初始化列表显式调用基类构造函数
    {
        m_school = school;
    }
    QString cl_student::getName() const
    {
        return (m_school + " " + this->cl_person::getName()); //调用基类的公有函数,由于要重写而同名,故用作用域解析运算符
    }                                                         //无重名发生时,直接调用即可
    
    //main.cpp
    #include <qDebug>
    #include <student.h>
    #include <iostream>
    int main()
    {
        cl_person* p_cl_person[2];      //定义指向基类的指针,一个数组表示多种类型的对象,体现多态性
    
        int a;
        for(int i = 0;i < 2;i++)
        {
            std::cout << "enter 0 to creat cl_person,1 to creat cl_person" << std::endl;
            std::cin >> a;
            if(a == 0)      //根据用户选择的不同创建不同类型的对象
                p_cl_person[0] = new cl_person();
            else if(a == 1)
                p_cl_person[1] = new cl_student("dwp",24,"uestc");
            else
            {
                std::cout << "please enter 0 or 1" << std::endl;
                i--;
            }
        }
        for(int i = 0;i < 2;i++)
        {
            qDebug() << p_cl_person[i]->getAge();
            qDebug() << p_cl_person[i]->getName();
        }
        return 0;
    }
    

    在这里插入图片描述

    1.3 抽象基类(ABC)

    • 在C++中函数声明了就必须定义,否则会报错。C++中函数声明了就必须定义
    • C++通过使用纯虚函数提供未实现的函数,纯虚函数声明的结尾处为=0。
    virtual double Area() const = 0;
    
    • 类声明中包含纯虚函数时,不能创建该类的对象,这个类为抽象基类。只有派生类重写了这个纯虚函数后,才能创建类对象。
    • 纯虚函数也可以包含定义,但只要它是纯虚函数,就不能创建类对象。
    展开全文
  • c++类继承关系

    2012-10-23 16:57:38
    c++类继承关系 Hierarchy Chart 继承关系 基类CObject派生出的各类,MSDN中用
  • C++ 继承与派生实例详解 继承性是面向对象程序设计最重要的特性之一,使软件有了可重用性,C++提供的继承机制。 继承与派生的概念 一个新从已有的那里获得已有的特性,这种现象称为继承。同样也可以...
  • c++ 继承

    千次阅读 2022-03-23 21:51:43
    c++最重要的特征是代码重用,通过继承机制可以利用已有的数据类型来定义新的数据类型,新的不仅拥有旧的成员,还拥有新定义的成员。 一个 B 类继承于A,或称从 A 派生 B。这样的话, A 成为基类(父类)...

    一、类的基本概念

    c++最重要的特征是代码重用,通过继承机制可以利用已有的数据类型来定义新的数据类型,新的类不仅拥有旧类的成员,还拥有新定义的成员。 一个 B 类继承于A类,或称从类 A 派生类 B。这样的话,类 A 成为基类(父类), 类B成为派生 类(子类)。 派生类中的成员,包含两大部分: 一类是从基类继承过来的,一类是自己增加的成员。 从基类继承过过来的表现其共性,而新增的成员体现了其个性。

    继承的优点:减少代码的冗余 提高代码的重用性

    二、继承的格式

    派生类定义格式:

    Class 派生类名 : 继承方式 基类名{

                   //派生类新增的数据成员和成员函数

    };

    三种继承方式: public : 公有继承 private : 私有继承 protected : 保护继承 从继承源上分: 单继承:指每个派生类只直接继承了一个基类的特征 多继承: 指多个基类派生出一个派生类的继承关系,多继承的派生类直接继承了不止一个基 类的特征

    派生类访问控制:

     

     三、对象构造和析构的调用原则

    继承中的构造和析构 子类对象在创建时会首先调用父类的构造函数 父类构造函 数执行完毕后,才会调用子类的构造函数 当父类构造函数有参数时,需要在子类 初始化列表(参数列表)中显示调用父类构造函数 析构函数调用顺序和构造函数相 反

    class A{
    public:
    A(){
    cout << "A 类构造函数!" << endl;
    }
    ~A(){
    cout << "A 类析构函数!" << endl;
    }
    };
    class B : public A{
    public:
    B(){
    cout << "B 类构造函数!" << endl;
    }
    ~B(){
    cout << "B 类析构函数!" << endl;
    }
    };
    class C : public B{
    public:
    C(){
    cout << "C 类构造函数!" << endl;
    }
    ~C(){
    cout << "C 类析构函数!" << endl;
    }
    };
    void test(){
    C c;
    }
    

      四、子类中的构造

    Son(int a,int b):Base(a),b(b)
    {
    //this‐>b = b;
    }
    class Base
    {
    private:
     int a;
     public:
    
     Base()
     {
     cout<<"父类的无参构造函数"<<endl;
     }
     Base(int a)
     {
     this‐>a = a;
     cout<<"父类的有参构造函数"<<endl;
     }
     ~Base()
     {
     cout<<"父类中的析构函数"<<endl;
     }
     };
     class Son:public Base
     {
     private:
     int b;
     public:
     Son()
     {
     cout<<"子类的无参构造"<<endl;
     }
     Son(int b)
     {
     this‐>b = b;
     cout<<"子类的有参构造函数int"<<endl;
     }
    
     //子类必须用 初始化列表 显示的调用父类的有参构造
     //父类名称(参数)
     Son(int a,int b):Base(a)//显示的调用父类的有参构造
     {
     this‐>b = b;
     cout<<"子类的有参构造函数 int int"<<endl;
     }
     ~Son()
     {
     cout<<"子类中的析构函数"<<endl;
     }
     };
     void test01()
     {
     //子类 默认 会调用 父类的无参构造
     //Son ob1(10);
    
     //子类必须用 初始化列表 显示的调用父类的有参构造
     //父类名称+()
     Son ob2(10,20);

    在实现子类构造函数时,使用初始化列表调用父类的构造函数。

    五、继承中同名成员的处理方法

    当子类成员和父类成员同名时,子类依然从父类继承同名成员 如果子类有成员和 父类同名,子类访问其成员默认访问子类的成员(本作用域,就近原则) 在子类通 过作用域::进行同名成员区分(在派生类中使用基类的同名成员,显示使用类名限定 符)

    class Base{
    public:
    Base():mParam(0){}
    void Print(){ cout << mParam << endl; }
    public:
    int mParam;
    };
    class Derived : public Base{
    public:
    Derived():mParam(10){}
    void Print(){
    //在派生类中使用和基类的同名成员,显示使用类名限定符
    cout << Base::mParam << endl;
    cout << mParam << endl;
    }
    //返回基类重名成员
    int& getBaseParam(){ return Base::mParam; }
    public:
    int mParam;
    };
    int main(){
    Derived derived;
    //派生类和基类成员属性重名,子类访问成员默认是子类成员
    cout << derived.mParam << endl; //10
    derived.Print();
    //类外如何获得基类重名成员属性
    derived.getBaseParam() = 100;
    cout << "Base:mParam:" << derived.getBaseParam() << endl;
    return EXIT_SUCCESS;
    }
    注意: 如果重新定义了基类中的重载函数,将会发生什么?
    class Base{
    public:
    void func1(){
    cout << "Base::void func1()" << endl;
    };
    void func1(int param){
    cout << "Base::void func1(int param)" << endl;
    }
    void myfunc(){
    cout << "Base::void myfunc()" << endl;
    }
    };
    class Derived1 : public Base{
    public:
    void myfunc(){
    cout << "Derived1::void myfunc()" << endl;
    }
    };
    class Derived2 : public Base{
    public:
    //改变成员函数的参数列表
    void func1(int param1, int param2){
    cout << "Derived2::void func1(int param1,int param2)" << en
    dl;
    };
    };
    class Derived3 : public Base{
    public:
    //改变成员函数的返回值
    int func1(int param){
    cout << "Derived3::int func1(int param)" << endl;
    return 0;
    }
    };
    int main(){
    Derived1 derived1;
    derived1.func1();
    derived1.func1(20);
    derived1.myfunc();
    cout << "-------------" << endl;
    Derived2 derived2;
    //derived2.func1(); //func1 被隐藏
    //derived2.func1(20); //func2 被隐藏
    derived2.func1(10,20); //重载 func1 之后,基类的函数被隐藏
    derived2.myfunc();
    cout << "-------------" << endl;
    Derived3 derived3;
    //derived3.func1(); 没有重新定义的重载版本被隐藏
    derived3.func1(20);
    derived3.myfunc();
    return EXIT_SUCCESS;
    }

    1、当 父类和子类 成员变量同名时 在子类就近原则 选择本作用域的子类 成员

    2、如果在子类中 必须使用父类中的同名成员 必须加上父类的作用域。 

    3、子类可以借助父类的公有方法间接的操作父类的私有数据(不可见的数据)

    展开全文
  • C++类继承

    千次阅读 2022-02-06 21:33:16
    10.1定义子类对象,包含父类成员,内存分布先父类后子类 (1)定义子类对象包含父类 (2)内存分布先父类后子类 ...(1)定义子类对象,构造顺序,父类->...(1)不使用继承的示例代码 #include<ios

    10.1定义子类对象,包含父类成员,内存分布先父类后子类

    (1)定义子类对象包含父类

    (2)内存分布先父类后子类

    10.2

    (1)定义子类对象,构造顺序,父类->子类,父类的默认无参构造可以自动调用

    (2)如果父类中无无参的构造函数,仅有带参构造函数,那么在子类的初始化列表中手动调用父类带参的构造函数

    (3)子类对象、生命周期结束时,调用析构顺序是子类-父类

    (错误写法)

    (正确写法)

    10.3继承的好处

    (1)不使用继承的示例代码

    #include<iostream>

    using namespace std;

    class CYellowPeo

    {

    public:

    int m_money;

    void cost(int a)

    {

    m_money-=a;

    }

    void eat()

    {

    cout<<"五常大米"<<endl;

    }

    };

    class CWhitePeo

    {

    public:

    int m_money;

    void cost(int a)

    {

    m_money-=a;

    }

    void eat()

    {

    cout<<"牛排"<<endl;

    }

    };

    class CBackPeo

    {

    public:

    int m_money;

    void cost(int a)

    {

    m_money-=a;

    }

    void eat()

    {

    cout<<"牛排"<<endl;

    }

    };

    int main()

    {

    system("pause");

    return 0;

    }

    (2)使用继承的父类代码

    #include<iostream>

    using namespace std;

    class CPeople

    {

    int m_money;

    void cost(int a)

    {

    m_money-=a;

    }

    };

    class CYellowPeo:public CPeople

    {

    public:

    void eat()

    {

    cout<<"五常大米"<<endl;

    }

    };

    class CWhitePeo:public CPeople

    {

    public:

    void eat()

    {

    cout<<"牛排"<<endl;

    }

    };

    class CBackPeo:public CPeople

    {

    public:

    void eat()

    {

    cout<<"牛排"<<endl;

    }

    };

    int main()

    {

    system("pause");

    return 0;

    }

    即对比上述代码可得到继承的好处如下:
    将一些功能相似的公共成员,单独抽离出来形成一个类,这个类就是父类,子类继承父类,包含了这些公共的成员,即提高了代码的复用性、扩展性、后期更容易维护。

    复用性:可重复使用的功能。

    扩展性:只需在父类增加所需功能,其余子类不需更改。

    10.4继承的方式:描述了父类成员在子类中所表现的属性。

    (1)public:公有继承:

           父类                            子类    

    <1>public                        public

    <2>protected                  protected  

    <3>private                       不可访问

    实例代码

    #include<iostream>

    using namespace std;

    class CFather

    {

    public:

    int m_pub;

    protected:

    int m_pro;

    private:

    int m_pri;

    };

    class CSon:public CFather

    {

    public:

    void show_public()

    {

    cout<<m_pub<<endl;

    cout<<m_pro<<endl;

    //cout<<m_pri<<endl;不可访问

    }

    };

    class CSonson:public CSon

    {

    void show_test()

    {

    cout<<m_pro<<endl;

    cout<<m_pub<<endl;

    }

    };

    int main()

    {

    CSon son;

    system("pause");

    return 0;

    }

    (2)protected:保护继承

    <1>public                        protected  

    <2>protected                  protected  

    <3>private                       不可访问

    同理,私有的依旧不可访问

    示例代码

    #include<iostream>

    using namespace std;

    class CFather

    {

    public:

    int m_pub;

    protected:

    int m_pro;

    private:

    int m_pri;

    };

    class CSon:protected CFather

    {

    public:

    void show_protected()

    {

    cout<<m_pub<<endl;

    cout<<m_pro<<endl;

    //cout<<m_pri<<endl;

    }

    };

    class CSonson:protected CSon

    {

    void show_test()

    {

    cout<<m_pro<<endl;

    cout<<m_pub<<endl;

    }

    };

    int main()

    {

    CSon son;

    cout<<son.m_pro<<endl;

    cout<<son.m_pub<<endl;

    system("pause");

    return 0;

    }

    (3)private:私有继承

    <1>public                        private

    <2>protected                  private

    <3>private                       不可访问

    均是不可访问

    示例代码

    #include<iostream>

    using namespace std;

    class CFather

    {

    public:

    int m_pub;

    protected:

    int m_pro;

    private:

    int m_pri;

    };

    class CSon:private CFather

    {

    public:

    void show_private()

    {

    cout<<m_pub<<endl;

    cout<<m_pro<<endl;

    //cout<<m_pri<<endl;

    }

    };

    class CSonson:private CSon

    {

    void show_test()

    {

    cout<<m_pro<<endl;

    cout<<m_pub<<endl;

    }

    };

    int main()

    {

    CSon son;

    cout<<son.m_pro<<endl;

    cout<<son.m_pub<<endl;

    system("pause");

    return 0;

    }

    10.5隐藏

    对于函数重载而言,我们调用的时候,可以根据参数类型、参数个数,编译器环境自动区分该具体调用的哪个函数,同样如果一个类小红存在两个同名函数(参数列表不同),那么也可以根据调用者传递的参数自动的区分执行哪个函数,因为这也是一个函数重载的关系。

    那么对于父类和子类,如果有同名的函数但是参数列表不同,则不能够自动区分,因为他们之间的关系并不是函数重载的关系,作用域不同,必须使用类名::去区分到底该调用哪个函数。子类中的重名函数我们谓之为隐藏。

    示例代码

    #include<iostream>

    using namespace std;

    class CFather

    {

    public:

    void show(int a,int b,int c)

    {

    cout<<a<<" "<<b<<" "<<c<<endl;

    }

    };

    class CSon:public CFather

    {

    public:

    void show(int a)

    {

    cout<<a<<endl;

    }

    void show(int a,int b)

    {

    cout<<a<<" "<<b<<endl;

    }

    };

    int main()

    {

    CSon son;

    son.show(10);

    son.show(10,20);

    //son.show(10,20,30);

    son.CFather::show(10,20,30);

    system("pause");

    return 0;

    }

    展开全文
  • C++类继承(终极版)简单易懂

    千次阅读 多人点赞 2022-04-24 00:19:13
    大家好,这里是小张,今天给大家带来的是C++类继承终极篇,今天小张会把剩下的继承内容全部说完,希望能够帮助到大家,话不多说,我们现在就开始。首先先来说说在继承中同名成员的处理方式:如果是访问子类...
  • C/C++ 公有继承、保护继承和私有继承的区别  在c++继承控制中,有三种不同的控制权限,分别是public、protected和private。定义派生时,若不显示加上这三个关键字,就会使用默认的方式,用struct定义的是默认...
  • C++类继承中的几个常用关键字

    千次阅读 2018-03-19 10:01:16
    C++编程中,尤其是对于大型的项目,正确的使用关键字能有效的避免我们犯错误,下面列出几个常用的关键字来巩固...当一个中出现一个该方法时,则该即为抽象,抽象不能直接创建对象必须被继承。override:该...
  • C++类继承内存布局文档打包
  • C++ MSDN的总图,显示了所有 之间的关系 非常有用!~~
  • C++习题 多重继承

    2016-07-07 12:59:31
    c++多重继承的一个习题
  • C++11:继承构造函数

    千次阅读 2022-03-13 15:33:40
    } 继承构造函数 以上方法虽然可行,但是代码非常繁琐切重复性高,而C++11中的继承构造函数特征正是用于解决派生隐藏基类同名函数的问题。 可以通过 using Base::SomeFunction来表示使用基类的同名函数。 所以以上...
  • C++ 中私有继承的作用

    2020-12-25 19:16:39
    C++ 中私有继承的作用 私有继承的 第一个规则:和公有继承相反,如果两个之间的继承关系为私有,编译器一般不会将派生对象转换成基类对象。 第二个规则: 从私有基类继承而来的成员都成为了派生的私有成员,...
  • C++ 继承详解

    万次阅读 2022-02-21 20:04:49
    C++ 继承继承语法继承方式改变访问权限名字遮蔽继承时的对象模型无变量遮蔽有变量遮蔽 继承语法 继承的一般语法为: class 派生类名:[继承方式] 基类名{ 派生新增加的成员 }; 继承方式 继承方式包括 public...
  • C++ --模板之模板的继承

    千次阅读 2022-03-21 00:20:11
    模板的继承 1、如果父类是一个模板,那么子类继承父类时一定要指出父类模板的数据类型 2、如果子类不想指定父类模板数据类型,那么子类也要变成一个模板 //模板的继承 //1.如果父类是一个模板,那么...
  • 构造方法用来初始化的对象,与父类的其它成员不同,它不能被子类继承(子类可以继承父类所有的成员变量和成员方法,但不继承父类的构造方法)。因此,在创建子类对象时,为了初始化从父类继承来的数据成员,系统...
  • C++继承中的权限

    2022-03-03 16:00:26
    文章目录一、默认权限二、默认继承权限(1)class 继承 struct(2)struct 继承 class三、继承权限探究(1)公有继承(2)私有继承(3)保护继承四、继承和派生中定义基类成员权限的区别 一、默认权限 struct 默认...
  • C++类继承:派生的构造函数

    千次阅读 2019-04-29 11:27:54
    这意味着派生的构造函数必须使用基类的构造函数来设置从基类中继承的私有成员。 因此,在程序使用派生构造函数创建派生对象之前,要使用基类构造函数创建基类对象。C++中,使用成员初始化列表完成这种工作。 ...
  • C++类继承实例

    2012-04-22 17:02:46
    三个源代码介绍继承,多继承,虚基类。通过VC++编译。
  • C++继承和多态

    千次阅读 2022-01-29 16:06:04
    继承和派生可以在不破坏原有的封装特性的情况下获得原有的数据和功能,并在此基础上增加新的数据和功能。基类是为解决以前的老问题而设计的,但在遇到新问题时其功能就有局限,这是在继承的基础上进行派生则能够...
  • C/C++类继承

    万次阅读 多人点赞 2019-01-24 17:15:26
    继承 class Shape{ }; class Circle : public Shape{ }; 语法:class B : public A{} B继承于A,A是父类,B是派生(子类) 当 B继承于A时,自动将父类中的所有public 成员继承,无法继承private的 ...
  • c++ 继承构造函数

    千次阅读 2021-10-11 17:17:04
    c++ 继承构造函数 class TestA { public: TestA(string i): a(i) {} ~TestA() {} string geta() { return a; } virtual string getb() = 0; private: string a; }; class TestB: public TestA{ public: ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 379,950
精华内容 151,980
关键字:

c++类的继承