C++:继承

一.继承的引出

class News
{
public:
    void header()
    {
        cout<<"header"<<endl;
    }
    void footer()
    {
        cout<<"footer"<<endl;
    }
    void left()
    {
        cout<<"left"<<endl;
    }
    void content()
    {
        cout<<"content"<<endl;
    }
};

void test01()
{
    News news;
    news.header();
    news.footer();;
    news.left();
    news.content();

    News yule;
    yule.header();
    yule.footer();;
    yule.left();
    yule.content();
}

//继承引出
//抽象一个基类的网页 重复的代码都写到这个网页上


//基类
class BasePage
{
public:
    void header()
    {
        cout<<"header"<<endl;
    }
    void footer()
    {
        cout<<"footer"<<endl;
    }
    void left()
    {
        cout<<"left"<<endl;
    }

};

//派生类
class New:public BasePage  //继承
{
public:
    void content()
    {
        cout<<"content"<<endl;
    }
};
class Yule:public BasePage
{
    public:
    void content()
    {
        cout<<"Yule"<<endl;
    }
};

class Game:public BasePage
{
    public:
    void content()
    {
        cout<<"LOL"<<endl;
    }
};


void test02()
{
    New news;
    news.content();
    news.footer();
    news.header();
    news.left();

    Yule yu;
    yu.footer();
    yu.header();
    yu.left();
    yu.content();

}

二.3种继承方式

1.公有继承

class Son1:public Base1
{
public:
    void Func()
    {
        cout<<m_A<<endl;
        cout<<m_B<<endl;       //保护模式 类外不能访问
//        cout<<m_C<<endl;      //私有模式 无法访问
    }

};
//保护继承
class Son2:protected Base1
{
public:
    void Func()
    {
        cout<<m_A<<endl;//继承为保护模式 类外不可访问
        cout<<m_B<<endl;//继承为保护模式 类外不可访问
    }

};
void myFunc()
{
    Son1 son1;
    son1.m_A;
//    son1.m_B; //无法访问

      Son2 son2;
//      son2.m_A;//不可访问
//      son2.m_B; //不可访问
}

2.保护继承

class Son2:protected Base1
{
public:
    void Func()
    {
        cout<<m_A<<endl;//继承为保护模式 类外不可访问
        cout<<m_B<<endl;//继承为保护模式 类外不可访问
    }

};
void myFunc()
{
    Son1 son1;
    son1.m_A;
//    son1.m_B; //无法访问

      Son2 son2;
//      son2.m_A;//不可访问
//      son2.m_B; //不可访问
}

3.私有继承

class Son:public Base1
{
public:
    int m_D;

};
void test03()
{
    cout<<sizeof(Son)<<endl;  //16  表明子类会继承基类的私有成员,但被编译器隐藏,导致访问不到
}

三.继承中的构造和析构

class Base3
{
public:
    Base3()
    {
        cout<<"gouzao"<<endl;
    }
    ~Base3()
    {
        cout<<"xigou"<<endl;
    }
};
class Son3 :public Base3
{
public:
    Son3()
    {
       cout<<"Son3 gouzao"<<endl;
    }
    ~  Son3()
    {
        cout<<"Son3 xigou"<<endl;
    }

};

void test04()
{
    Base3 b3;

    Son3 s3;  //先构造父类 再构造本身 先析构自身 再析构父类
}
//子类可以继承父类的成员属性和函数
//子类不会继承父类的构造和析构函数
//只有父类自己知道如何构造和析构自身的属性

class Base4
{
public:
//用户自定义了有参构造 和系统不再管理默认构造
    Base4(int a)
    {
        this->m_A = a;
        cout<<"arg gouzao"<<endl;
    }
    int m_A;
};

class Son4:public Base4
{
public:
    Son4(int a):Base4(a)      //由于构造子类时必须先进行父类的默认构造,而父类已经没有了默认构造,所以需要利用初始化列表的方式显式调用父类的有参构造
    {
        cout<<" Son4 gouzao"<<endl;

    }
};

void test05()
{
   Son4 s4(1000);       //子类构造传参给父类构造
}

四.继承中的同名处理

1.普通同名成员函数和成员属性

//继承中的普通同名处理
class Base5
{
public:
    Base5()
    {
        m_A= 100;
    }

    void func()
    {
        cout<<"Base5 func"<<endl;
    }
    int m_A;
};
class Son5 :public Base5
{
   public:
    Son5()
    {
        m_A = 200;
    }

    void func()
    {
        cout<<"Son5 func"<<endl;
    }

    int m_A;
};
//针对子类与父类中存在同名函数或属性的问题
//如果子类和父类有同名函数和属性 子类不会覆盖父类
//如果子类存在与父类的成员函数名相同的函数,子类会把父类所有的同名版本都隐藏,使子类不能访问
//想调用父类的方法,必须加作用域
void test06()
{
    Son5 s5;
    cout<<s5.m_A<<endl;  //200 就近原则 调用了zi'lei子类的m_A


    //如何调用父类中的m_A呢?
    cout<<s5.Base5::m_A<<endl;  //输出 100

    //同名函数处理方式相同

        s5.func();
        s5.Base5::func();
}

2.静态同名成员函数和属性


//继承中同名静态成员的处理
class Base6
{
public:
    //静态成员属性 类内定义 类外初始化
    static int m_A;
};
int Base6::m_A = 10;

class Son6:public Base6
{

};


void test07()
{
    //说明子类可以继承父类的静态成员属性
    cout<<Son6::m_A<<endl; //10
}

//当子类中出现同名静态成员属性时
class Base7
{
public:
    static void func()
    {
        cout<<"Base7 func"<<endl;
    }

    static void func(int a)
    {
        cout<<"Base7 func int"<<endl;
    }



    //静态成员属性 类内定义 类外初始化
    static int m_A;
};
int Base7::m_A = 10;

class Son7:public Base7
{
public:
    static void func()
    {
        cout<<"Son7 func"<<endl;
    }


    static int m_A;
};
int Son7::m_A = 20;

void test08()
{
    //说明子类隐藏了父类中的同名静态成员变量 如果访问,则需要加父类作用域
    cout<<Son7::m_A<<endl; //20
    cout<<Base7::m_A<<endl; //10

    Son7::func(); //调用了子类的静态成员函数 隐藏了弗雷所用的同名静态成员函数
//    Son7::func(10); //报错 说明子类隐藏了父类中的同名静态成员函数
    //调用父类中与子类同名的函数
    Son7::Base7::func();
    Base7::func();
}

五.多继承问题及其解决

//多继承
class Base8
{
public:
    Base8()
    {
        m_A = 10;
    }
    int m_A;
};
class Base9
{
public:
    Base9()
    {
        m_A = 20;
    }
    int m_A;
};
class Son8:public Base8,public Base9
{
public:
    int m_C;
    int m_D;
};

void test09()
{
    cout<<sizeof(Son)<<endl;  //16
    Son8 s8;
    //    cout<<s8.m_A<<endl;    //出现二义性 无法确定是哪一个父类的成员  多继承较容易出现二义性

    cout<<s8.Base8::m_A<<endl;  //10 通过作用域来解决二义性
}

六.菱形继承问题及解决

class Animal
{
public:
    int m_Age;
};
//菱形继承
//虚基类
class Sheep:virtual public Animal
{
public:
};
class Tuo:virtual public Animal
{
};
class SheepTuo :public Sheep,public Tuo
{
};

//菱形继承问题的解决 利用虚继承 virtual
void test10()
{
    SheepTuo st;
    st.Sheep::m_Age = 10;
    st.Tuo::m_Age = 20;
    //如果class Sheep和class Tuo不加virtual关键字,虽然实际都是继承了Animal 但却可以出现不同的值 这是有问题,而且如果不加作用域,会出现二义性
//    cout<<st.Sheep::m_Age<<endl;  //10
//    cout<<st.Tuo::m_Age <<endl;     //20
    //添加virtual关键字,让Sheep和Tuo类都虚继承Animal  其继承的成员属性都指向animal  即共享一份数据
    //不加作用域也不会出现二义性
    cout<<st.Sheep::m_Age<<endl;     //20
    cout<<st.Tuo::m_Age <<endl;     //20
    cout<<st.m_Age <<endl;          //20
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Michael.Scofield

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值