总结-----继承和多态

之所以把继承和多态放在一起,是因为二者在关系上很难分开。

继承的概念:

在已有类的基础上创建新类。新类包含了原始类的数据成员和方法。

创建新类的主要原因就是添加替换功能。

继承从两个方面去讨论:

添加:扩展原有类的成员(变量和方法),在继承的基础上扩展

继承的运行方式是单向的,父类与子类有着明确的关系,子类知道与父类的关系,但是父类不知道与子类的关系。

其实这样记不好记,从内存的角度去记比较好记。

从内存的大小上看很好区分。

Father* p_father = new Son;   // ok;
Son *p_son = new Father;         // error
  

所以基类指针可以指向父类

Father *p_father;p_father的寻址能力Father类的大小。

Son* p_son;p_son的寻址能力Son类的大小。

Father* p_father = new Son;   // ok;

new Son寻址的空间大于p_father的寻址分为,所以ok
Son *p_son = new Father;         // error

new Father寻址的空间小于p_father的寻址分为,所以error,出界。

#include <iostream>
using namespace std;

class Father
{
public:
	virtual int fun(int a)
	{
		cout << "call father fun(int a)" << endl;
		return 0;
	}
};

class Son : public Father
{
public:
	virtual int fun(int a)
	{
		cout << "call son fun(int a)" << endl;
		return 0;
	}
};


int main(void)
{

	Father* father = new Son;
	father->fun(10);

	return 0;
}

    Father* father = new Son;
    father->fun(10);
 

派生类的角度看

我可以访问积累中的protected,和public数据。

 

禁止继承

c++有一个关键字可以禁止一个类被继承。关键字是final,只需要在类的名字后面加上final关键字。

class A final
{

}

 

替换:重写原有类的成员函数换(重写):

学好继承区别这两个概念很重要:重载和重写

区别:重载,在同一作用域内,所发生的关系。而重写是类与类之间的关系。且基类有关键字virtual(换句话说就是发生在继承中的现象)

学好继承区别这两个概念很重要:重写和覆盖

区别:如果基类中没有关键字virtual,那他一定是覆盖。有关键字virtual一定是重写。记得重写和覆盖都是对于子类对于父类来说的。

我们知道重载函数与返回值类型无关,那么重写和覆盖也和返回值类型无关。

一下例子区分者四个概念:

#include <iostream>
using namespace std;

class Father
{
public:
	void fun()
	{
		cout << "call father fun()" << endl;
	}

	virtual int fun(int a)
	{
		cout << "call father fun(int a)" << endl;
		return 0;
	}
};

class Son : public Father
{
public:
	void fun()
	{
		cout << "call son fun()" << endl;
	}

	virtual int fun(int a)
	{
		cout << "call son fun(int a)" << endl;
		return 0;
	}
};


int main(void)
{

	Father* father = new Son;
	father->fun();
	father->fun(10);

	return 0;
}

我们说过没有virtual关键字且只要函数名相同就会发生将函数名相同的全覆盖。很显然

father->fun()被覆盖。记住是对于子类来说father->fun()被覆盖。

virtual int fun(int a) 很显然基类有关键字virtual所以是重写。

    father->fun(); // 输出结果,call father fun(); // 覆盖是对子类来说的。father是分类。
    father->fun(10); // 输出结果,call son fun();   // 重写,且要知道一个概念。

重点讲这句:    

    Father* father = new Son;
    father->fun(10); 

由于c++是静态语言,而有了virtual虚函数则变为动态的函数,所以,father->fun(10);的输出结果会是call son fun();

father指针指向的内容并没有变,只不过是带有Virtual关键字的函数替换了。这就叫动态编译。

接着上图:

Father里的fun()和Father里的fun(int a)  重载。

Son里的fun()和Son里的fun(int a)  重载。

Father里的函数与Son里的函数不在同一作用域内,所以不存在重载,这是类与类之间的关系,只存在覆盖和重写。

 

 

最后一个关键字override

既然基类中有关键字override,就是重写了,那为什么还会有override关键字呢???

override存在的好处之一是,检查此函数是否是真正的重写,如果有关键字override而基类中没有关键字virtual则会报错。

另一个好处,是保证其为真重写,不存在错误。有了override则必须保证重写函数参数列表一模一样,返回值类型可以不一样。

总结起来就是:override就是一个重写函数的保险。

例子:

#include <iostream>
using namespace std;

class Father
{
public:
    virtual void fun()
    {
        cout << "called Father fun()" << endl;
    }
    virtual void fun(int a)
    {
        cout << "called Father fun()" << endl;
    }
};

class Son:public Father
{
public:
    virtual void fun() override    
    {
        cout << "called Son fun()" << endl;
    }
    virtual void fun(char a) // 没有override
    {
        cout << "called Son fun()" << endl;
    }
};



int main(void)
{

    Father* father  = new Son;
    father->fun();
    father->fun(10);

    return 0;
}

输出结果:

fun()是真重写,而 virtual void fun(char a) // 没有override,因为参数列表不同,所以irtual void fun(char a) 只是一个新的virtual函数,而不是重写函数。

 

 

多态:其实上面已经用到了多态知识只是没总结。

多态:

同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。

    Father* father = new Son;
    father->fun();

此方法就是多态。但是要注意,十分注意;实现多态的方式是指针或引用这两种

    Father father;
    Son son;
    father = son;
    father.fun();
    father.fun(10);

 

输出结果:

 

 

还是从内存的角度去分析:

father = son;虽然将father强制转换为son但是,father所对应的内存并没有改变,还是那么大,

 

    Father father;
    Son son;

    cout << &father << endl;
    father = son;
    cout << &father << endl;

所以 father.fun();  father.fun(10);结果还是father fun() 和 father fun(int a).


 

总结:继承中包含多态,只是多态的形成需要一定的条件,需要重写。重写就是多态。(重写需要虚函数)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值