cpp学习笔记:继承

一、构造功能

在一些重复内容中,往往我们会进行多次复制相同的变量或者函数在不同的类中,此时我们可以选择新建一个父类,把重复的内容写在父类内,把不同的内容在子类中单独写。然后使用子类继承父类的内容,以达到减少代码量的作用。

class BasePage
{ 
public:
    void header()
    {
        cout << "首页、公开课、登录、注册...(公共头部)" << endl;
    } 
    void footer()
    {
        cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;
    } 
    void left()
    {
        cout << "Java,Python,C++...(公共分类列表)" << endl;
    }
};


class Java : public BasePage
{ 
public:
    void content()
    {
        cout << "JAVA学科视频" << endl;
    }
};


class Python : public BasePage
{
public:
    void content()
    {
        cout << "Python学科视频" << endl;
    }
};


class CPP : public BasePage
{
    public:
    void content()
    {
        cout << "C++学科视频" << endl;
    }
};


void test01()
{

    cout << "Java下载视频页面如下: " << endl;
    Java ja;
    ja.header();
    ja.footer();
    ja.left();
    ja.content();
    cout << "--------------------" << endl;

    cout << "Python下载视频页面如下: " << endl;
    Python py;
    py.header();
    py.footer();
    py.left();
    py.content();
    cout << "--------------------" << endl;

    cout << "C++下载视频页面如下: " << endl;
    CPP cp;
    cp.header();
    cp.footer();
    cp.left();
    cp.content();

} 

int main() {
    test01();

    system("pause");
    return 0;
}

二、继承的格式

class A:public B

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

三、继承方式

1、公有继承:class son:public Base

①以下为父类

class Base1
{
public:
    int m_A;
protected:
    int m_B;
private:
    int m_C;
};

②以下为子类,公有继承的子类可以访问父类的public和protected中的内容,不可以访问private

class son1:public Base1
{
public:
    void func()
    {
        m_A;
        m_B;
        //m_C;
    }
};

③以下为其他类,不是子类,只能访问public中的内容

void myclass()
{
    son1 sn;
    sn.m_A;
}

2、保护继承:class son:protected Base

①以下为父类

class Base2
{
public:
    int m_A;
protected:
    int m_B;
private:
    int m_C;
};

②以下为子类,保护继承的子类可以访问父类的public和protected中的内容,不可以访问private,此时父类中的公共类型,到子类中变为保护权限。

class son2:protected Base2
{
public:
    void func()
    {
        m_A;
        m_B;
        //m_C;
    }
};

③以下为其他类,不是子类,进行保护继承后,父类中的公共类型,到子类中变为保护权限,所以不能访问

void myclass2()
{
    son2 sn;
//   sn.m_A;
}

3、私有继承:class son:private Base

①以下为父类

class Base3
{
public:
    int m_A;
protected:
    int m_B;
private:
    int m_C;
};

②以下为子类,私有继承的子类可以访问父类的public和protected中的内容,不可以访问private,此时父类中的公共类型,到子类中变为私有权限。

class son3:private Base3
{
public:
    void func()
    {
        m_A;
        m_B;
        //m_C;
    }
};

③对第一次中的子类再次进行继承,因为第一次继承已经成私有,所以再次继承都不会被访问到。

class sonson3:public son3
{
public:
    void func()
    {
        //m_A;
        //m_B;
        //m_C;
    }
};

四、继承中的对象模型

问:从父类继承过来的成员,哪些输入子类对象中?

class Base
{
public:
    int m_A;
protected:
    int m_B;
private:
    int m_C;
};

class son:public Base
{
public:
    int m_D;
};


void test01()
{
    cout << sizeof(son) << endl;
}

int main()
{
    test01();

    system("pause");
    return 0;
}

执行程序后输出:16,这说明父类的所有内容包括私有成员m_C也被继承了,只是被隐藏了访问不到。

五、继承中构造和析构顺序

问:父类和子类构造和析构顺序是谁先谁后?

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 s;
}

以下为编译结果,继承中,先调用父类的构造函数,再调用子类的构造函数,析构函数相反。所有构造执行完毕之后才会执行析构函数。

 六、继承同名成员处理方式

1、访问子类同名成员,直接访问即可

访问父类同名成员,需要加作用域

class Base
{
public:
    Base()
    {
        m_A=100;
    }

    void func()
    {
        cout << "base func()调用" << endl;
    }

    void func(int a)
    {
        cout << "base func(int a)调用" << endl;
    }

public:
    int m_A;
};


class Son:public Base
{
public:
    Son()
    {
        m_A = 200;
    }

    void func()
    {
        cout << "son func()调用" << endl;
    }

public:
    int m_A;
};
void test01()
{
    Son s;

    cout << s.m_A << endl;
    cout << s.Base::m_A << endl;

    s.func();
    s.Base::func();
    s.Base::func(10);
}

2、输出结果

3、总结

①子类对象可以直接访问子类中的同名成员

②子类对象加作用域可以访问到父类同名成员

③当子类与父类拥有同名的成员函数,子类会隐藏父类中所有版本的同名成员函数,如果想访问父类中被隐藏的同名成员函数,需要加父类的作用域

七、静态同名静态成员处理方式

1、静态成员和非静态成员出现同名,处理方式一致

访问子类同名成员,直接访问即可;访问父类同名成员,需要加作用域。

2、同名静态成员处理方式有两种访问方式,通过对象访问和通过类名访问

void test01()
{
    cout << "通过对象访问: " << endl;
    Son s;
    s.func();
    s.Base::func();

    cout << "通过类名访问: " << endl;
    Son::func();
    Son::Base::func();
    //出现同名,子类会隐藏掉父类中所有同名成员函数,需要加作作用域访问
    Son::Base::func(100);
}

八、多继承语法

C++允许一个类继承多个类

语法:class 子类:继承方式  父类1,继承方式  父类2 .......

多继承可能会引发父类中有同名成员出现,需要加作用域区分

class Base1
{
public:
    Base1()
    {
        m_A=100;
    }

public:
    int m_A;
};

class Base2
{
public:
    Base2()
    {
        m_A=200;
    }

public:
    int m_A;
};

class Son:public Base2,public Base1
{
public:
    

};

void test01()
{
    Son s;
    //cout << s.m_A << endl;  //出现重复,报错,需要加作用域
    cout << s.Base1::m_A << endl;
    cout << s.Base2::m_A << endl;
}

 九、菱形继承

1、两个子类继承同一个基类,又有某个类同时继承两个子类,这种继承称为菱形继承,或者钻石继承。

2、羊继承了动物的数据,驼同样继承了动物的数据,当草泥马使用数据时,就会产生二义性。草泥马继承自动物的数据继承了两份,其实我们应该清楚,这份数据我们只需要一份就可以。

class Animial
{
public:
    int m_Age;
};

class Sheep: public Animial{};

class Tuo: public Animial{};

class SheepTuo:public Sheep,public Tuo{};


void test01()
{
    SheepTuo st;
    st.Sheep::m_Age = 100;
    st.Tuo::m_Age = 200;

    cout << st.Sheep::m_Age << endl;
    cout << st.Tuo::m_Age << endl;
    //cout << st.m_Age << endl;  //报错
}

此时输出的数值为100  200,最后的报错,注释掉。

class Animial
{
public:
    int m_Age;
};

class Sheep:virtual public Animial{};

class Tuo:virtual public Animial{};

class SheepTuo:public Sheep,public Tuo{};


void test01()
{
    SheepTuo st;
    st.Sheep::m_Age = 100;
    st.Tuo::m_Age = 200;

    cout << st.Sheep::m_Age << endl;
    cout << st.Tuo::m_Age << endl;
    cout << st.m_Age << endl;
}

假如virtual关键字后,变为虚继承,输出200 200 200,st.m_Age也不会报错

3、菱形继承带来的主要问题是子类继承两份相同的数据,导致资源浪费以及毫无意义,利用虚继承可以解决菱形继承问题。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值