C++自学笔记(day6)

五、继承和派生

1.派生一个类

​ 继承方式(默认为私有继承)

特征公有继承保护继承私有继承
公有成员公有成员保护成员私有成员
保护成员保护成员保护成员私有成员
私有成员私有成员只能通过基类接口访问只能通过基类接口访问
向上隐式转换是(但只能在派生类中)
inherit.cpp
#include <iostream>
#include <string.h>
/*
派生一个子类,子类继承父类的所有成员和成员函数(默认为私有继承)
    公有继承:继承过来的成员 权限不变
        父类         子类
        public    -> public
        protected -> protected
        private   -> 不可见(只能通过基类接口访问)
    保护继承:
    	public	  -> protected
    	protected -> protected
    	private   -> 不可见(只能通过基类接口访问)
    私有继承:
    	public	  -> 不可见(只能通过基类接口访问)
    	protected -> 不可见(只能通过基类接口访问)
    	private   -> 不可见(只能通过基类接口访问)
*/
using namespace std;
class father{
public:
    double money;
    char name[12];
    char *GetFName(){
        return name;
    }
protected:
    void SetMoney(double m);
private:
    int eyes;
};

class son : public father{
public:
    char name[12];          //派生类中有基类同名成员时,将会 隐藏 基类同名的成员,也就是既有自己的name,也有基类的name
    void GetMoney(){
        money = 2000;       //公有继承时,在派生类内部, 可以  直接访问基类 公有成员
        SetMoney(1000);     //公有继承时,在派生类内部, 可以  直接访问基类 受保护成员
        //eyes = 2;         //公有继承时,在派生类内部,不可以 直接访问基类 私有成员
    }
    char *GetSName(){
        return name;
    }
protected:
private:
};

int main()
{
    son obj;
    obj.money = 1000;       //公有继承时,在派生类外部, 可以  通过对象访问 公有成员
    //obj.setMoney(2000);   //公有继承时,在派生类外部,不可以 通过对象访问 受保护成员
    //obj.eyes = 2;         //公有继承时,在派生类外部,不可以 通过对象访问 私有成员
    
    strcpy(obj.name, "zhangsan");
    strcpy(obj.father::name, "lisi");   //子类和父类有相同成员,可以通过作用域访问符访问父类同名成员
    cout << obj.GetSName() << endl;
    cout << obj.GetFName() << endl;
}

2.派生类的构造和析构

inherit.cpp
#include <iostream>
/*
    1.继承时的构造顺序:
        先基类构造,再派生类构造
    ----------析构顺序:
        先派生类析构,再基类析构
    2.包含对象成员的派生类的构造顺序:
        先基类构造,再对象成员构造,最后派生类构造
    ----------析构顺序:
        先派生类析构,再对象成员析构,最后基类析构
*/
using namespace std;
#define pri() cout<<"line: "<<__LINE__<<" func: "<<__func__<<endl;
class A{
public:
    A(){ pri(); }
    ~A(){ pri(); }
};

class Base{
public:
    Base(){ pri(); }
    ~Base(){ pri(); }
};

class Subclass : public Base{
public:
    Subclass(){ pri(); }
    ~Subclass(){ pri(); }
    A a;
};
int main()
{
    Subclass obj;
    return 0;
}
inherit.cpp
#include <iostream>
/*
1.派生类构造函数参数初始化列表中,隐式调用基类默认无参构造
2.如果基类出现有参构造,必须在派生类的构造函数参数初始化列表中显式调用基类有参构造
3.如果派生类对象成员的构造函数带参数,必须在派生类的构造函数初始化列表中,为对象成员赋初值
*/
using namespace std;
#define pri() cout<<"line: "<<__LINE__<<" func: "<<__func__<<endl;

class A{
public:
    A(){ pri(); }
    A(int x){ pri(); }
};

class Base{
public:
    Base(){ pri(); }
    Base(int x):x(x){ pri(); }
    ~Base(){ pri(); }
private:
    int x;
};

class Subclass : public Base{
public:
    Subclass(){ pri(); }
    Subclass(int x):a(x),Base(x){ pri(); }
    ~Subclass(){ pri(); }
private:
    A a;
};

int main()
{
    Subclass obj1;
    Subclass obj2(3);
    return 0;
}

3.默认向上隐式转换

inherit.cpp
#include <iostream>
using namespace std;
#define pri() cout<<"line: "<<__LINE__<<" func: "<<__func__<<endl;

class Base{
public:
    Base(int x):x(x){  }
    int GetValue(){
        return x;
    }
private:
    int x;
};

class Subclass : public Base{
public:
    Subclass(int x, int y):x(x), Base(y){  }
    int GetX(){
        return x;
    }
private:
    int x;
};

int main()
{
    Subclass obj(10, 20);
    Base B(0);

    cout << obj.GetValue() << endl;
    cout << B.GetValue() << endl;
#if 1
    B = obj;        //默认向上隐式转换。将派生类对象赋值给基类对象时,将派生类类型转换成基类类型,
                    //派生类将会丢弃自身的数据部分,也称为小范围赋值给大范围
    cout << B.GetValue() << endl;
#else
    obj = B;        //向下转换是不被允许的,不允许将大范围赋值给小范围
#endif
    return 0;
}

4.多重继承

名字二义性 inherit.cpp
#include <iostream>
using namespace std;
#define pri() cout<<"Line: "<<__LINE__<<endl;

class A{
public:
    void prnmsg(){ pri(); }
};

class B{
public:
    void prnmsg(){ pri(); }
};

class C:public A, public B{
public:
};

int main()
{
    C obj;
    //obj.prnmsg();   //多重继承的名字二义性,解决办法:作用域访问符
    obj.A::prnmsg();
    obj.B::prnmsg();
    return 0;
}
路径二义性 inherite.cpp
#include <iostream>
using namespace std;
#define pri() cout<<"Line: "<<__LINE__<<endl;
class Base{
public:
    void prnmsg(){ pri(); }
};

class A:public Base{
public:
};

class B:public Base{
public:
};

class C:public A, public B{
public:
};

int main()
{
    C obj;
    //obj.prnmsg();   //多重继承的路径二义性,解决方法:作用域访问符或者
    //虚基类(虚继承(继承时有virtual关键字修饰)共同的基类)
    obj.A::prnmsg();
    obj.B::prnmsg();
    return 0;
}

C++自学笔记(day7)
C++自学笔记(目录)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值