C++学习笔记——类和对象——继承

生来就可爱ヽ(ⅴ<●) 提交于 2020-02-28 03:32:41

继承是面向对象的三大特性之一,下图展示了一些类与类之间的关系。

可以看出来,下层级别的成员除了拥有上一层的共性,还有自己的特性,这个时候就需要考虑用继承的技术以减少重复代码。

继承的语法:

class A: 继承方式 B; 

A类称为子类或者派生类,B类称为父类或者基类,子类中的成员包含两个部分,一部分是从父类继承过来的,另一部分是自己增加的成员,从父类继承过来的表现共性,新增的成员体现个性。

class Animal{
public:
    void information(){
        cout<<"我是一只动物"<<endl;
    }
};

class Dog:public Animal{
public:
    void dog(){
        cout<<"我是一只狗"<<endl;
    }
};

class Hashiqi:public Dog{
public:
    void hashiqi(){
        cout<<"我是一只二哈"<<endl;
    }
};

void test01(){
    Hashiqi hashiqi;
    hashiqi.information();
    hashiqi.dog();
    hashiqi.hashiqi();
}

 继承的方式:

继承方式一共有三种:

公共继承;

保护继承;

私有继承。

继承中的对象模型:

从父类中继承过来的成员,哪些属于子类对象,下面通过一段代码测试一下。

class Base
{
public:
    int m_A;
protected:
    int m_B;
private:
    int m_C; //私有成员只是被隐藏了,但是还是会继承下去
};

//公共继承
class Son :public Base
{
public:
    int m_D;
};

void test01()
{
//    结果为sizeof Son =16
    cout << "sizeof Son = " << sizeof(Son) << endl;
}

可以看出,父类和子类共有4个int类型的成员,Son类的大小为16,所以得出父类中的私有成员也会被子类继承下去,只是被编译器隐藏了所以才会访问不到。

 继承中构造和析构顺序:

子类继承父类后,当创建子类对象时,也会调用父类的构造函数,那么父类和子类构造和析构的顺序是怎样的呢,下面通过一段代码测试一下。

class Base
{
public:
    Base(){
        cout<<"Base的构造函数"<<endl;
    }
    ~Base(){
        cout<<"Base的析构函数"<<endl;
    }
};

//公共继承
class Son :public Base
{
public:
    Son(){
        cout<<"Son构造函数"<<endl;
    }
    ~Son(){
        cout<<"Son析构函数"<<endl;
    }
};

void test01(){
    Son son;
}

执行结果如下图:

 

 可以看出,继承中,先调用父类的构造函数,再调用子类的构造函数,析构顺序与构造顺序相反。

继承同名成员处理方式:

当子类和父类出现同名的成员,怎么通过子类对象,访问子类或者父类中的同名数据呢,有下面三条规则:

1.子类对象可以直接访问到子类中的同名成员;

2.子类对象加作用域可以访问到父类中的同名成员;

3.当子类与父类有同名的成员函数,子类会隐藏父类中同名的成员函数,加作用域可以访问到父类中的同名函数。

下面是一个简单的例子:

class Base{
public:
    Base(){
        m_a=10;
    }
    void function(){
        cout<<"Base--function的调用"<<endl;
    }

public:
    int m_a;
};

class Son:public Base{
public:
    Son(){
        m_a=20;
    }
    void function(){
        cout<<"Son--function的调用"<<endl;
    }
public:
    int m_a;
};

void test01(){
   Son son;

   cout<<"Son下的m_a"<<son.m_a<<endl;
   cout<<"Base下的m_a"<<son.Base::m_a<<endl;

   son.function();
   son.Base::function();
}

菱形继承:

概念:两个子类继承同一个父类,又有某个类同时继承这两个子类,这种继承称为菱形继承。

下面是一个菱形继承的例子:

菱形继承带来的问题是子类继承两份相同的数据,导致资源浪费,所以采用虚继承来解决菱形继承带来的问题。

下面是一个简单的例子:

 

class Animal{
public:
    int m_age;
};

class Ma:virtual public Animal{};

class Lv:virtual public Animal{};

class LuoZi:public Ma,public Lv{};

void test01(){
    LuoZi luoZi;
    luoZi.Ma::m_age=10;
    luoZi.Lv::m_age=5;

    cout<<luoZi.Ma::m_age<<endl;
    cout<<luoZi.Lv::m_age<<endl;
    cout<<luoZi.m_age<<endl;
}

 

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!