div KenID:Kendiv
395312次访问,排名124好友0人,关注者2
Kendiv的文章
原创 155 篇
翻译 42 篇
转载 71 篇
评论 221 篇
Kendiv的公告
我们家最坏的就是他~~ 我的mimi,可爱吧~~
2008.08.22
Coding Life
/*---------------------
Personal Info:
Name: Kendiv
----------------------*/
最近评论
muchool:http://cvsproxy.muchool.com/ 专门针对软件开发人员量身定做的CVS代理下载,无需安装任何CVS客户端,轻松而快速的打包下载CVS版本控制服务器上的资源,自动剔除版本控制信息,还原开发者的原始项目目录.
ruanjian311:受益匪浅
mohroq:wow gold,
AloneSword:我喜欢 你家的 那个最坏的。
wanttocto:谢谢兄弟!!!
可以发一份中英文都有的给我吗?
xiao_17_xiao@126.com
文章分类
收藏
相册
AI
智能中国
AntiVirus
Malware-Research‏
AV Engine
a tool to collect malware
ClamAV for Windows
ClamAV Virus Database
ClamAV-Home
Disassembly Challenges
Filetype Detection - wiki
IceSword - Home
OpenAnti-Virus
BBS、论坛
Juniper Networks
Visual Studio Team System - 微软中文技术社区
ChinaUnix Blog
飞翔,嵌入式linux
Data Loss Prevention (DLP) Security
Hacker
Collection.Sites
Z0MBiE's HomePage
ICAP
ICAP-Forum
POSIX Threads(PThreads)
Open Source POSIX Threads for Win32
Squid
squid-home
Virtualization
虚拟机之家
Web Tech.
Https - wiki
ICP - Home
技术网站
absurd,大牛
ChinaUnix
Cisco Systems
CSDN
DDK MVP Expert Zone
Dr. Dobb's Journal
Ethereal
Kernel Mustard的专栏
Linux Journal
LinuxAid 技术支持中心
Microsoft Systems Journal
Microsoft TechNet
MSDN 技术资源库
MSDN中文WebCast
SysInternals(FreeWare)
The Code Project
VCHelp
VC在线
VC知识库
Windows Driver Programming(WD-3)
ZDNet China
中国协议分析网
哈工大·纯C论坛
安全焦点
微软中国社区
绿盟技术版
罗云彬的编程乐园
驱动开发网
其他
前程无忧
数字北京
清韵书院
铁血军事网
铁血读书
网上书店
China-Pub
第二书店
友情链接
JoyCode博客堂
Rong
嵌入式软件开发网(UCSDN)
狗狗
邹欣的Blog
存档
订阅我的博客
XML聚合  FeedSky

转载 谈谈C++继承中的重载,覆盖和隐藏收藏

新一篇: static用法小结 | 旧一篇: GCC精彩之旅

谈谈C++继承中的重载,覆盖和隐藏

      写正题之前,先给出几个关键字的中英文对照,重载(overload),覆盖(override),隐藏(hide)。在早期的C++书籍中,可能翻译的人不熟悉专业用语(也不能怪他们,他们不是搞计算机编程的,他们是英语专业的),常常把重载(overload)和覆盖(override)搞错!

  我们先来看一些代码及其编译结果。

  实例一:
  
  #include "stdafx.h"
  #include <iostream.h>

  class CB
  {
  public:
     void f(int)
     {
        cout << "CB::f(int)" << endl;
     }

  };


  class CD : public CB
  {
  public:
     void f(int,int)
     {
        cout << "CD::f(int,int)" << endl;
     }

     void test()
     {
       f(1);
     }
  };

 int main(int argc, char* argv[])
 {
    return 0;
 }
编译了一下
error C2660: 'f' : function does not take 1 parameters


结论:在类CD这个域中,没有f(int)这样的函数,基类中的void f(int)被隐藏

  如果把派生CD中成员函数void f(int,int)的声明改成和基类中一样,即f(int),基类中的void f(int)还是一样被覆盖,此时编译不会出错,在函数中test调用的是CD中的f(int) 

  所以,在基类中的某些函数,如果没有virtral关键字,函数名是f(参数是什么我们不管),那么如果在派生类CD中也声明了某个f成员函数,那么在类CD域中,基类中所有的那些f都被隐藏。
  如果你比较心急,想知道什么是隐藏,看文章最后的简单说明,不过我建议你还是一步一步看下去。

  我们刚才说的是没有virtual的情况,如果有virtual的情况呢??
  实例二:

#include "stdafx.h"
#include <iostream.h>

class CB
{
public:
   virtual void f(int)
   {
      cout << "CB::f(int)" << endl;
   }

};


class CD : public CB
{
public:
   void f(int)
   {
      cout << "CD::f(int)" << endl;
   }

};

int main(int argc, char* argv[])
{
  return 0;
}

  这么写当然是没问题了,在这里我不多费口舌了,这是很简单的,多态,虚函数,然后什么指向基类的指针指向派生类对象阿,通过引用调用虚函数阿什么的,属性多的很咯,什么??你不明白??随便找本C++的书,对会讲多态和虚函数机制的哦!!
  这种情况我们叫覆盖(override)!覆盖指的是派生类的虚拟函数覆盖了基类的同名且参数相同的函数!
  在这里,我要强调的是,这种覆盖,要满足两个条件
 (a)有virtual关键字,在基类中函数声明的时候加上就可以了
 (b)基类CB中的函数和派生类CD中的函数要一模一样,什么叫一模一样,函数名,参数,返回类型三个条件
  有人可能会对(b)中的说法质疑,说返回类型也要一样??
  是,覆盖的话必须一样,我试了试,如果在基类中,把f的声明改成virtual int f(int),编译出错了
  error C2555: 'CD::f' : overriding virtual function differs from 'CB::f' only by return type or calling convention
  所以,覆盖的话,必须要满足上述的(a)(b)条件

  那么如果基类CB中的函数f有关键字virtual ,但是参数和派生类CD中的函数f参数不一样呢,
实例三:
  #include "stdafx.h"
#include <iostream.h>

class CB
{
 public:
    virtual  void f(int)
   {
      cout << "CB::f(int)" << endl;
   }

}
;


class CD : public CB
{
public:
    void f(int,int)
   {
     cout << "CD::f(int,int)" << endl;
   }

   void test()
   {
      f(1);
   }
}
;

int main(int argc, char* argv[])
{
 return 0;
}

编译出错了,
 error C2660: 'f' : function does not take 1 parameters
  咦??好面熟的错??对,和实例一中的情况一样哦,结论也是基类中的函数被隐藏了。

  通过上面三个例子,得出一个简单的结论
如果基类中的函数和派生类中的两个名字一样的函数f
满足下面的两个条件
(a)在基类中函数声明的时候有virtual关键字
(b)基类CB中的函数和派生类CD中的函数一模一样,函数名,参数,返回类型都一样。
那么这就是叫做覆盖(override),这也就是虚函数,多态的性质

那么其他的情况呢??只要名字一样,不满足上面覆盖的条件,就是隐藏了。

下面我要讲最关键的地方了,好多人认为,基类CB中的f(int)会继承下来和CD中的f(int,int)在派生类CD中构成重载,就像实例一中想像的那样。
  对吗?我们先看重载的定义
  重载(overload):
  必须在一个域中,函数名称相同但是函数参数不同,重载的作用就是同一个函数有不同的行为,因此不是在一个域中的函数是无法构成重载的,这个是重载的重要特征
  必须在一个域中,而继承明显是在两个类中了哦,所以上面的想法是不成立的,我们测试的结构也是这样,派生类中的f(int,int)把基类中的f(int)隐藏了
  所以,相同的函数名的函数,在基类和派生类中的关系只能是覆盖或者隐藏。

  在文章中,我把重载和覆盖的定义都给了出来了,但是一直没有给隐藏的定义,在最后,我把他给出来,这段话是网上google来的,比较长,你可以简单的理解成,在派生类域中,看不到基类中的那个同名函数了,或者说,是并没有继承下来给你用,呵呵,如实例一 那样。
  

隐藏(hide):
指的是派生类的成员函数隐藏了基类函数的成员函数.隐藏一词可以这么理解:在调用一个类的成员函数的时候,编译器会沿着类的继承链逐级的向上查找函数的定义,如果找到了那么就停止查找了,所以如果一个派生类和一个基类都有同一个同名(暂且不论参数是否相同)的函数,而编译器最终选择了在派生类中的函数,那么我们就说这个派生类的成员函数"隐藏"了基类的成员函数,也就是说它阻止了编译器继续向上查找函数的定义

发表于 @ 2006年04月25日 04:29:00|评论(loading...)|编辑

新一篇: static用法小结 | 旧一篇: GCC精彩之旅

评论

#BOSAID 发表于2006-04-25 09:33:00  IP: 222.69.25.*
好文章,加精
#nanyu 发表于2006-04-25 18:43:00  IP: 222.76.149.*
关于覆盖(override):这句话不太完整:
(b)基类CB中的函数和派生类CD中的函数要一模一样,什么叫一模一样,函数名,参数,返回类型三个条件。
事实上,返回值可以不一样也可以构成override。前提是返回值是指针(或引用,少见),并且指向类系中的派生类即可。
class Base
{
};

class Derive : public Base
{};

class A
{
vritual Base* foo();
};
class B : public A
{
virtual Derive* foo();
};
++++++++++++++++++
关于隐藏,也补充一句,可以在通过在派生类中,采用using语句,达到对被隐藏的函数。为什么呢?因为在C++中,class是一个“准名字空间” (名字空间当然是一种域);多数情况下具备标准名字空间的用法,包括这里提到的using。
#jackywgw 发表于2006-10-29 22:05:00  IP: 218.108.88.*
看了你的文章后,大受启发,但还有一事求教:
当基类有virtual,基类和派生类中有同名函数,且参数相同,但返回值不同时为什么会出错?原理是什么?
这种情况当然不是覆盖,但为什么不是隐藏呢?
#centsky 发表于2007-04-19 10:10:47  IP: 125.216.249.*
大受启发,谢谢楼主!
发表评论  


当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
Csdn Blog version 3.1a
Copyright © Kendiv