如何在派生类中的隐藏基类的虚拟重载函数?

2016-01-29 12:19 12 1 收藏

如何在派生类中的隐藏基类的虚拟重载函数?,如何在派生类中的隐藏基类的虚拟重载函数?

【 tulaoshi.com - C语言心得技巧 】

如何在派生类中的隐藏基类的虚拟重载函数?


作者:northtibet

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

    我创建了一个类,基类中有虚拟重载函数。我想在派生类中改写基类中的虚拟重载函数。代码如下:

#include <iostream.hclass B {private:   int nNumber;public:    virtual void test() {       cout << "B::test()n";  }     virtual void test(int x) {         nNumber = x; // 将传入的参数赋值给私有成员       cout << "B::test(int x)n";      }};class D : public B {public://test(void) 隐藏 B::test(int)    virtual void test() {       cout << "D::test()n";    }};void main(int argc, char* argv[]){  D d;          // 派生类的实例  d.test();       // OK  d.test(17);     // 产生编译错误的代码行}
    基类中有两个重载的test函数。当我在派生类中改写其中的一个函数时,我觉得另外一个应该在派生类中继承,但编译时出现一下错误信息:
... C2660 : ''test'' :function does not take 1 parameters

在不放弃多态行为的情况下,我能不能同时重载和改写某个函数?

    许多C++程序员都对这个问题感到困惑,为了解开这个惑点,有两个概念你必须要了然于心。一个是重载,一个是名字空间。从重载的视角看,你可能觉得C++应该按照你所想象的方式工作;也就是如果派生类只修改其中的一个重载函数的行为,那么另外一个应该按照通常的方式被继承。但从名字空间的角度看,当C++试图解决某个符号名时,它以由近到远的顺序进行搜索,它首先找本地变量,然后是类成员名,接着是基类名,全局变量……。一旦编译器解析了名字,它便终止解析过程。如果在不同的名字空间范围碰到同一个符号名,那么它便没有了主意。在你的代码中,一旦编译器确定名字"test"出现在类D中,那么它的名字空间就为类D。不论你调用不带参数的test也好,还是调用带一个整型参数的test(17)也好,编译器都是遵循准这个规则来解决名字问题。对于有整型参数的test(int x)函数,一旦编译器确定函数名test生存在类D中,它便终止范围探查,然后查找与参数匹配的函数。由于它没有在类D中找到带整型参数的函数,所以报错。此时编译器认为函数D::test(void)隐藏了函数B::test(int)。你可能会问,为什么要按这种方式处理?问得好。想找到答案,请参考Bjarne Stroustrup 的C++注释参考手册(Section 13.1)。简单地说,在类层次深处搜索与某个签名匹配的重载函数比不搜索更可能导致混乱。
那么如何解决上面出现的问题呢?很容易。只要在派生类中创建另一个显式调用基类的test函数即可,如:
class D : public B {public:  virtual void test(int x) { B::test(x); }  ……};
这样,D就有了两个test函数,问题也解决了。 其实这个问题还有另外一个解法:那就是在派生类中使用"using"关键字。如:
class D : public B {public:using B::test;// 改写test virtual void test() {     cout << "D::test()n";}};    
    这个关键字将B::test带入类D中。它的优点是当类B扩展更多的test重载函数时,你不用再去重写类D的代码。这样省了很多事。只要你使用using关键字,那么就意味着所有重载的B::test函数都进入类D并且得到继承。这种特性可能对于某些人来说是优点,而对于另外一些人来说是缺点,依赖于你要做什么事情。如果你想要向类D的用户隐藏某些test函数,则可以用第一种方法(显式调用基类),或者让你想要隐藏的函数成为private 或 protected类型。如果你读过Scott的书《Effective C++》,还可以用第二种方法利用using关键字巧妙地保证基类的私隐。
class B {public:    func1();    func2(double d);    virtual test();    virtual test(int x);};// D 从B中秘密派生class D : private B {public:    // 让所有 B::test 函数为 public类型    using B::test;};
显然,当希望完全隐藏类B时,这个方法很有用,但如果想要公开B中的个别函数,则这个方法就不是那么好了。

来源:https://www.tulaoshi.com/n/20160129/1485575.html

延伸阅读
标签: Web开发
javascript不能支持函数的重载,如下: 代码如下: script language="JavaScript" function f(length) {     alert("高为:"+length); } function f(length,width) {     alert("高为:"+length+",宽为:"+width); } /srcipt 上面那段代码其实是行不通的,因为函数定义时...
  函数重载是用来描述同名函数具有相同或者相似功能,但数据类型或者是参数不同的函数治理操作的称呼。 !-- frame contents -- !-- /frame contents -- 我们来举一个实际应用中的例子来说明问题:我们要进行两种不同数据类型的和操作为了实现它,在c语言中我们就要写两个不同名称的涵数来进行区分例...
CButtonST类公共接口函数 作者:杜修杏 以下是CButtonST类的所有公共成员函数(函数名按音序排列先后): CButtonST::DrawBorder DWORD DrawBorder(BOOL bDrawBorder = TRUE, BOOL bRepaint = TRUE) 注释: 因为CButtonST的默认显示风格是平面按钮。调...
标签: Web开发
比如我们要在一个类中设定一个方法可以根据调入一个方法保存在类变量中,等需要的时候可以通过访问类变量来得到。 通常如果我们生成一个实例 如:var temp=new TopnetTree(); 如果我们通过设定属性的方式来传入一个方法,会发现传入的是一个函数的内容,而非函数名。 如temp.fileAction=fnTest; //fnTest是一个函数 于是偶...
如何在Dll中导出STL类 作者:yy2better 关键字:DLL STL 简介:本文详述在DLL中导出stl类及包含stl的类的方法。例子源码 Dll无法直接导出泛型模板(generalized template),因此,如果要导出stl类,则模板必须先实例化(instantiated)。另外,如果导出的S...

经验教程

48

收藏

81
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部