effective C++ 读书笔记 条款12与条款13

条款12:确定你的public继承塑膜出is-a关系:

这个条款主要将了一些特殊情况:比如企鹅是鸟,企鹅可以继承于鸟,但是鸟会飞,企鹅却不能飞;还有让正方形继承矩形可能也会造成这种尴尬!

这个问题以前想过,但是不知道怎么解决,如果现实生活当中确实要这么使用:比如 猫 狗 鱼  猪等等许多动物继承Animal类,但是猫狗等不会游泳,

假如这里是有很多动物,不能采用鱼里面专门加一个方法!  这个现在还没想出来,条款12也没有讲如果要这么用该怎么处理就是将要避免这样。

 

is - a;

在面向对象程序设计里面,ia - a指的是类的父子继承关系;

public继承就意味着 is - a ,适用于base - class 身上的每一件事情也一定适应于derived class身上。因此每一个子类对象也是一个父类对象。

 

条款13:避免遮掩继承而来的名称:

这个条款主要讲了遮掩继承,其实也就是我们经常说的 重载 重写(覆盖) 隐藏;下面就看一下 重载 重写 隐藏的区别:

1、重载的特征:在同一个类中;函数名字相同;参数不同;virtual 关键字可有可无。
2、重写(覆盖)特征是:分别位于派生类与基类;函数名字相同;参数相同;基类函数必须有virtual 关键字(这点非常要注意)。

关于隐藏:


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

 

// 06.cpp : 定义控制台应用程序的入口点。
//
/************************************************************************/
/* 目的:找出重载、重写、隐藏的区别
	时间:2014年12月1日 19:06:03
*/
/************************************************************************/

#include "stdafx.h"
#include <iostream>
using namespace std;


class Base
{
private:
	int x;
public:
	virtual void mf1() = 0;
	virtual void mf1(int) //重载,在同一个类当中或者说同一个工作区间内。
	{
		cout<<"调用基类的mf1函数"<<endl;
	}
	virtual void mf2()
	{
		cout<<"调用基类的mf2函数"<<endl;
	}
	void mf3()
	{
		cout<<"调用基类的mf3函数"<<endl;
	}
	void mf3(double)
	{
		cout<<"调用基类的mf3重载函数"<<endl;
	}
};

class Derived:public Base
{
public:
	virtual void mf1()
	{
		cout<<"调用子类的mf1函数"<<endl;
	}
	void mf3()
	{
		cout<<"调用子类的mf3函数"<<endl;
	}
	void mf4()
	{
		cout<<"调用子类的mf4函数"<<endl;
	}
};

int _tmain(int argc, _TCHAR* argv[])
{

	Derived d;
	int x;
	d.mf1();//调用子类的mf1函数  这就是重写(覆盖)这是动态多态的最根本原因


	//d.mf1(x);//error C2660: “Derived::mf1”: 函数不接受 1 个参数;
	//虽然基类Base当中有mf1(int)函数,但是因为子类当中自己也有mf1()函数
	//所以发生了隐藏


	d.mf2();//这个没有任何问题,子类继承父类的函数,子类当中没有自己的mf2()函数,于是调用父类的函数


	d.mf3();//调用子类的mf3()函数;这里基类当中的mf3()函数并没有virtual,但是调用的是子类的函数,说明子类的函数隐藏了父类的函数
	// 如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与重写混淆)。


	//d.mf3(x);//error C2660: “Derived::mf3”: 函数不接受 1 个参数
	//虽然基类当中有 mf3(double)函数,但是因为子类当中也有自己的mf3()函数
	//所以发生了隐藏

	/*
	从d.mf1(x)和d.mf3(x)可以看出 virtual void mf1(int)与 void mf3(double),一个有virtual一个没有virtual
	但是它们都发生了隐藏。
	*/

	getchar();
	return 0;
}


上面的代码应该很好的解释了三者的区别;在条款33里面说道如果不想子类隐藏父类的函数,那么在子类当中用using 声明式达到目标:

 

class Derived:public Base
{
public:
	
	virtual void mf1()
	{
		cout<<"调用子类的mf1函数"<<endl;
	}
	
	using Base::mf1;
	void mf3()
	{
		cout<<"调用子类的mf3函数"<<endl;
	}
	void mf4()
	{
		cout<<"调用子类的mf4函数"<<endl;
	}
};


 

 

 

 




 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。