【C++基础之十八】类继承中的隐藏规则

原创 2013年12月10日 15:01:46

原创作品,转载请标明http://blog.csdn.net/jackystudio/article/details/17243251


记得以前看林锐博士的《高质量C++编程指南》一书有提到类继承中的隐藏问题,当时网上也有不同的声音,觉得并没有隐藏这个东西,后来在看C++ primer的时候确实有提到这个问题(谓之“屏蔽”),这里记下来,如果理解有误,还请指出。


1.重载和覆盖

在了解隐藏之前,得先分清楚重载和覆盖。

(1)重载:对同一个类而言的,函数名相同,函参不同,因为是在同一个类中,所以是否是virtual并不重要。

(2)覆盖:对基类和派生类而言。函数名相同,函参相同,必须是virtual函数。

如下示例,1和2是重载关系,而1和3是覆盖关系。

class A{
public:
	virtual void fun(){cout<<"A::fun()";}//1
	void fun(int a){cout<<"A::fun(a)";}//2
};

class B : public A{
public:
	void fun(){cout<<"B::fun()";}//3
};

2.隐藏

首先隐藏也是发生对基类和派生类而言的,所以主要就是要理清隐藏和覆盖的差异。

(1)如上所述,覆盖要求是virtual函数,所以如果是不带virtual的同名同参函数,那么就是隐藏。

(2)不管有没有virtual标识,函参不一样,那么也是隐藏。

如下示例,1和3同名同参,但是无virtual标识,所以是隐藏。2和4函参不同,所以也是隐藏。

class A{
public:
	void fun1(){cout<<"A::fun1()";}//1
	virtual void fun2(int a){cout<<"A::fun2(a)";}//2
};

class B : public A{
public:
	void fun1(){cout<<"B::fun1()";}//3
	void fun2(){cout<<"B::fun2()";}//4
};


3.一种简单区分调用方法

如果对上面的重载,覆盖,隐藏还是搞不清楚,再加上多态的使用,更会是云里雾里。这里提供了一种方便理解的区分调用方法(From C++ primer)。

(1)首先确定进行函数调用的对象、引用或指针的静态类型

(2)在该类中查找函数,如果找不到,就在直接基类中查找,如此循着类的继承链往上找,直到找到该函数或者查找完最后一个类。如果不能在类或其相关基类中找到该名

字,则调用是错误的

(3)一旦找到了该名字,就进行常规类型检查,查看如果给定找到的定义,该函数调用是否合法。

(4)假定函数调用合法,编译器就生成代码。如果函数是虚函数且通过引用或指针调用,则编译器生成代码以确定根据对象的动态类型运行哪个函数版本,否则,编译器生成

代码直接调用函数。


4.示例

class A{
public:
	virtual void fun1(){cout<<"A::fun1()";}//1
	void fun2(){cout<<"A::fun2()";}//2
	virtual void fun3(){cout<<"A::fun3()";}//3
};

class B : public A{
public:
	void fun1(){cout<<"B::fun1()";}//4
	void fun3(int a){cout<<"B::fun3(a)";}//5
};

int _tmain(int argc, _TCHAR* argv[])
{
	B b;
	b.fun1();
	b.fun2();
	b.fun3(1);

	A* pa=new B();
	pa->fun1();
	pa->fun2();
	pa->fun3();
}
按照上述方法分析:

(1)B b。B类型,所以所有的调用要先在B类中查找。

fun1存在,所以调用4。

fun2不存在,所以在基类A中查找,存在fun2(),所以调用2。

fun3存在,但是要求带参,所以只能调用fun3(int a),如果b.fun3()则会报错,因为一旦找到名字就会停下,进行类型匹配检查。所以调用5。

(2)A* pa=new B()。A类型指针,所以所有的调用要现在A类中查找(此时不会再到B中查找,但不意味着不调用B中函数

fun1存在,因为new的是B的对象,而且是虚函数,所以到B中查找是否进行了覆盖,发现确实进行了覆盖,所以调用4。

fun2存在,调用2。

fun3存在,因为new的是B的对象,而且是虚函数,所以到B中查找是否进行了覆盖,发现没有有进行覆盖,所以调用3。



版权声明:本文为博主原创文章,未经博主允许不得转载。

燕十八老师讲的js,自己做的笔记,有点乱。供以后学习使用。。。。

javascript
  • Hxn_Fight
  • Hxn_Fight
  • 2015年04月01日 14:36
  • 1821

SVD分解的应用——矩阵运算和文本处理中的分类问题

在自然语言处理中,最常见的两类的分 类问题分别是,将文本按主题归类(比如将所有介绍亚运会的新闻归到体育类)和将词汇表中的字词按意思归类(比如将各种体育运动的名称个归成一类)。这两种 分类问题都可用通过...
  • xiaoyu714543065
  • xiaoyu714543065
  • 2012年08月01日 10:05
  • 891

2014年最新燕十八老师PHP视频教程10K月薪高性能架构班

链接: http://pan.baidu.com/s/1dDtNkLr 密码: cq92 加入QQ群:302040480,免费索取教程 具体目录: Linux优化篇1.mys...
  • n2dx83uc2
  • n2dx83uc2
  • 2014年09月17日 16:03
  • 1382

理解C++类的继承

本文讲述的是面向对象语言中类的继承的理解,文中以C++语言作为例子。 继承说明了类之间的层次结构的关系。C++中允许单继承,也允许多继承(一个类可以有多个基类) 类继承用一个冒号来表示,注意不要与作用...
  • xiahn1a
  • xiahn1a
  • 2014年12月05日 13:08
  • 1040

C++类的3种继承方式

简单地说下C++类的3种继承方式,分别是public继承,protected继承,private继承。 最常用的还是public继承。class默认的是private继承,它的member如果没...
  • zuihoudebingwen
  • zuihoudebingwen
  • 2013年08月26日 15:23
  • 1005

C++中名字隐藏是什么?

让我们通过一个例子来讲解C++中的名字隐藏。在C++中,如果一个类里有一个重载的方法, 你用另一个类去继承它并重写(覆盖)那个方法。你必须重写所有的重载方法, 否则未被重写的方法会因为名字相同而被隐藏...
  • banbanlin
  • banbanlin
  • 2014年09月25日 21:21
  • 1613

PHP大型门户网站核心技术之MySQL优化

课程简介: 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用系统提交实际应用后,随着数据库中数据的增加,系统的...
  • hefu1869
  • hefu1869
  • 2017年03月25日 21:49
  • 143

C++中的隐藏规则

C++中的隐藏规则如果派生类的函数与基类的函数同名,但是参数不同,此时,无论有无virtual关键字,基类的函数将被隐藏(重载是一个类中有同名的函数) 如果派生类的函数与基类的函数同名,并且参数也相同...
  • Docterzzz
  • Docterzzz
  • 2017年01月14日 18:38
  • 263

C++模板类的继承1 :模板类继承模板类

大学时代旧作。       模板类的继承是C++中较为高级的一种用法,其语法与普通C++类的继承略有差别。本文实例演示了一个通过C++模板类继承实现排序算法的案例。代码如下: 1.   实现List基...
  • u011747351
  • u011747351
  • 2013年08月25日 13:53
  • 1220

类(继承)的内存分配详解

1.基类与派生类的内存分配 派生类继承基类       内存分配时,是在于基类对象不同的内存地址处,按基类的成员变量类型,开辟一个同样的类型空间,但注意开辟后派生对象的空间,不是复制基类的成员的值...
  • vainlyhopelim
  • vainlyhopelim
  • 2015年08月18日 16:38
  • 1782
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【C++基础之十八】类继承中的隐藏规则
举报原因:
原因补充:

(最多只允许输入30个字)