c++之继承

继承是OOP思想中很重要的一个特性:
一.继承简介
继承是使用现有的类或接口,扩展所需的功能,从而达到代码的复用的目的。

关于继承,我们从五个问题着手,边解决问题边理解。
1.派生类都继承了基类的那些?
2.派生类继承基类成员的访问限定?
**3.**protected和private的区别?
4.不给定继承方式,默认继承方式为?
5.基类和派生类同名方法之间的关系?

二.继承
继承是使代码可以复用的重要手段,也是面向对象程序设计的核心思想之一。简单的说,继承是指一个对象直接使用另一对象的属性和方法。继承体现了面向对象程序设计的层次结构。C++中的继承关系就好比现实生活中的父子关系,原始类称为基类,继承类称为派生类,它们是类似于父亲和儿子的关系,所以也分别叫父类和子类。而子类又可以当成父类,被另外的类继承(这也就是多层继承关系)。继承的方式有三种,分别为公有继承(public),保护继承(protected),私有继承(private)。
三.继承方式和访问限定
(1) 公有继承(public)

公有继承的特点是基类的公有成员和保护成员作为派生类的成员时,它们都保持原有的状态,而基类的私有成员仍然是私有的,不能被这个派生类的子类所访问。

(2)保护继承(protected)

保护继承的特点是基类的所有公有成员和保护成员都成为派生类的保护成员,并且只能被它的派生类成员函数或友元访问,基类的私有成员仍然是私有的。
(3)私有继承(private)

私有继承的特点是基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问。
四.继承的简单应用和一些小问题
好啦,那我们先看段代码,看看继承的形式是什么样嗒!

class A
{
public:
private:
    int ma;
};

class B : public A//先不管类的那些构造析构函数,
//这里就是表示B继承了A,而且我给定的是公有继承
{
public:
private:
    int mb;
};

所以你认为我这样写可以吗?

class A
{
public:
    int ma;//这里
    int mb;
    int mc;
private:
};

class B : public A
{
public:
    int ma;//这里
    int mc;
    int md;
private:
};

就是说B继承了A,所以B中肯定有一个成员变量ma,是从A继承而来的,那自己还可以将成员变量名定义为ma吗?答案是肯定的,因为我们的派生类除了继承所有基类的成员意外,还会把基类的作用域继承来,所以,它存储空间应该这样的:
这里写图片描述


class Base
{
public:
    Base(int data = 10)
        :ma(data)
    {}
private:
    int ma;
};
class Derive : Base
{
public:
    Derive(int data = 10)
        :mb(data)
        ,ma(data)//初始化列表
    {}
private:
    int mb;
};

如果我写这样一个继承结构,你们觉得打印出来会是什么?(注意派生类的初始化列表)
是的,它会出现一个错误,是“成员Base::ma已经声明,不可访问”。所以说,我们在派生类中初始化基类的成员变量时应该用其作用域,而不是直接用成员变量,例如这个例子我们在派生类的初始化列表可以写为:

Derive(int data = 10)
        :mb(data)
        ,Base(data)
    {}

这样就好啦!


class Base
{
public:
    Base(int data = 10)
        :mb(data)
        ,ma(mb)
    {
        cout<<"ma:"<<ma<<endl;
        cout<<"mb:"<<mb<<endl;
    }
private:
    int ma;
    int mb;
};

那这个你觉得会打印什么??(这个不算继承的问题,突然就想起来了,就写一下)
这里写图片描述
答案是不是出乎意料。。。我记得老师讲课的时候问这个答案是什么,我想都没想就说10,10啊!!!然后老师瞥了我一眼,感觉当时的自己好愚蠢啊!
其实这个很简单,是和ma,mb的定义顺序有关,先定义的ma,就会先初始化ma,所以,当你用mb初始化ma时,就是随机数,因为这时mb还并没与初始化为10。为了有这种问题出现,我们不建议用一个成员变量初始化另一个哦!!
五.struct和class的区别
C++中的struct相比较于c语言的struct已经不再是一个结构体了,应该说也是一个类:

struct能包含成员函数吗? 能!
struct能继承吗? 能!!
struct能实现多态吗? 能!!!
最本质的一个区别就是默认的访问控制,体现在两个方面:
1)class中默认的成员访问权限是private的,而struct中则是public的。
2)“class”这个关键字还用于定义模板参数,就像“typename”。但关键字“struct”不用于定义模板参数。
3)class继承默认是private继承,而struct继承默认是public继承。
看了前边的内容,关于我开始提出的五个问题有答案了吗?我们一起来看看吧!

回答第一个问题:
派生类继承了基类除构造函数和析构函数以外的所有成员,并且继承了基类的作用域,所以基类和派生类的成员变量是可以重名的。
回答第二个问题:
这里写图片描述
回答第三个问题:
protected是保护的,private是私有的,在继承结构中,如果基类的某个成员不想让外部和派生类看见就可以定义为private,私有的成员变量可以被继承,但是不可以直接用,因为对于派生类来说,基类私有的成员变量是不可见的。但是,如果想要这个成员变量可以被派生类看见,但不想被外部使用,便可以定义为protected,它们在继承结构外是没有区别的。
回答第四个问题:
默认的继承方式取决于派生类而不是基类,我们知道,struct在c++中也是类结构,所以,class和struct有什么区别呢,其中很重要的一个就是默认继承方式不同,struct默认继承方式为public,class的默认继承方式为private。而我前面说的默认的继承方式取决于派生类而不是基类得意思是,派生类是class就会默认私有继承基类,派生类是struct就会默认公有继承基类。
回答第五个问题:
这段文字解释来自大神牛客网解释

1.成员函数被重载的特征:

(1)相同的范围(在同一个类中);

(2)函数名字相同;

(3)参数不同;

(4)virtual 关键字可有可无。

2.覆盖是指派生类函数覆盖基类函数,特征是:

(1)不同的范围(分别位于派生类与基类);

(2)函数名字相同;

(3)参数相同;

(4)基类函数必须有virtual 关键字。

3.“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:

(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。

(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值