重温《C++ Primer》笔记五 类定义中成员函数的名字隐藏(虚函数与非虚函数)

来源:互联网 发布:vb用的是什么语言 编辑:程序博客网 时间:2024/06/15 08:38

类定义中大致有两种函数——普通函数和虚函数。如果对一个类继承并且对其中的成员函数重新进行定义,也可以分为两种情况:

1、在派生类的定义中明确地定义操作和返回类型,称之为普通成员函数的重定义(redefining);

2、对虚函数的重定义成为重写(overriding);

下面的程序是摘自《Thinking in C++》上的一段,可以用来解释发生在函数重定义过程中的名字隐藏(这里的名字指的是函数的名字):

#include <iostream>#include <string>using namespace std;class Base{public:int f() const{cout<<"Base::f()\n";return 1;}int f(string) const {return 1;}void g() {}};class Derived1 : public Base{public:void g() const {}};class Derived2 : public Base{public:int f() const{cout<<"Derived2::f()\n";return 2;}};class Derived3 : public Base{public:void f() const{cout<<"Derived3::f()\n";}};class Derived4 : public Base{public:int f(int) const{cout<<"Derived4::f()\n";return 4;}};int main(){string s("hello");Derived1 d1;int x = d1.f();d1.f(s);Derived2 d2;x = d2.f();d2.f(s);return 0;}
首先,Derived1只重定义了父类的g()函数,没有对f()函数做任何的改变,因此调用f()的时候会自动调用父类的f()。并且f(s)在Derived1中也是可以使用的。

对于Derived2,它重定义了f()函数,而没有重定义f(s)函数,但是在这里却只能调用f()而不能调用f(s),即f(s)被隐藏了。

如果对Derived2修改一下,即重定义f()函数,也重定义f(s)函数,则两种都可以调用。

对于Derived3,它没有重定义基类中名为f的任何函数,而是通过修改返回值类型自己重新定义了一个名为f的函数,导致基类中的两个名为f的函数均不能被调用,即均被隐藏了。

对于Derived4,它没有重定义基类中名为f的任何函数,而是通过修改参数自己重新定义一个名为f的函数,导致基类中的两个名为f的函数均不能被调用,即均被隐藏了。

因此,可以得出一个结论:任何时候重新定义了基类中的一个重载函数,在新类之中所有其他的版本则被自动隐藏,除非在子类中全部重定义。


而对于虚函数的重写则有一点不同,即编译器不允许我们改变重定义过的函数的返回值类型(除了是将从基类引用或指针改为子类引用或指针),其它的则与重定义遵循一样的规则。这是为什么呢?在《Thinking in C++》上是这么说的:“因为编译器必须保证我们能够动态地通过基类调用函数,并且如果基类希望f()返回一个int值,则f()的派生类版本必须保持约定,否则将会出问题”。




0 0
原创粉丝点击