高质量C++/C编程指南-第8章-C++函数的高级特点(3)[VC/C++编程]
本文“高质量C++/C编程指南-第8章-C++函数的高级特点(3)[VC/C++编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
8.2.2 令人迷惑的躲藏法则
本来仅仅辨别重载与覆盖并不算艰难,但是C++的躲藏法则使问题复杂性陡然增添.这里“躲藏”是指派生类的函数屏蔽了与其同名的基类函数,法则以下:
(1)假如派生类的函数与基类的函数同名,但是参数差别.此时,不管有没有virtual关键字,基类的函数将被躲藏(注意别与重载混合).
(2)假如派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字.此时,基类的函数被躲藏(注意别与覆盖混合).
示例程序8-2-2(a)中:
(1)函数Derived::f(float)覆盖了Base::f(float).
(2)函数Derived::g(int)躲藏了Base::g(float),而不是重载.
(3)函数Derived::h(float)躲藏了Base::h(float),而不是覆盖.
#include <iostream.h>
class Base
{
public:
virtual void f(float x){ cout << "Base::f(float) " << x << endl; }
void g(float x){ cout << "Base::g(float) " << x << endl; }
void h(float x){ cout << "Base::h(float) " << x << endl; }
};
class Derived : public Base
{
public:
virtual void f(float x){ cout << "Derived::f(float) " << x << endl; }
void g(int x){ cout << "Derived::g(int) " << x << endl; }
void h(float x){ cout << "Derived::h(float) " << x << endl; }
};
示例8-2-2(a)成员函数的重载、覆盖和躲藏
据作者观察,很多C++程序员没有意识到有“躲藏”这回事.由于熟习不够深化,“躲藏”的发生可谓神出鬼没,常常产生令人迷惑的后果.
示例8-2-2(b)中,bp和dp指向同一地址,按理说运行后果应当是相同的,可事实并非这样.
void main(void)
{
Derived d;
Base *pb = &d;
Derived *pd = &d;
// Good : behavior depends solely on type of the object
pb->f(3.14f); // Derived::f(float) 3.14
pd->f(3.14f); // Derived::f(float) 3.14
// Bad : behavior depends on type of the pointer
pb->g(3.14f); // Base::g(float) 3.14
pd->g(3.14f); // Derived::g(int) 3 (surprise!)
// Bad : behavior depends on type of the pointer
pb->h(3.14f); // Base::h(float) 3.14 (surprise!)
pd->h(3.14f); // Derived::h(float) 3.14
}
示例8-2-2(b) 重载、覆盖和躲藏的对比
8.2.3 摆脱躲藏
躲藏法则惹起了不少麻烦.示例8-2-3程序中,语句pd->f(10)的本意是想调用函数Base::f(int),但是Base::f(int)不幸被Derived::f(char *)躲藏了.由于数字10不能被隐式地转化为字符串,所以在编译时出错.
class Base
{
public:
void f(int x);
};
class Derived : public Base
{
public:
void f(char *str);
};
void Test(void)
{
Derived *pd = new Derived;
pd->f(10); // error
}
示例8-2-3 由于躲藏而招致错误
从示例8-2-3看来,躲藏法则仿佛很笨拙.但是躲藏法则至少有两个存在的来由:
u 写语句pd->f(10)的人大概真的想调用Derived::f(char *)函数,只是他误将参数写错了.有了躲藏法则,编译器便可以明确指出错误,这未必不是功德.不然,编译器会静暗暗地将错就错,程序员将很难发现这个错误,流下祸根.
u 假定类Derived有多个基类(多重担当),有时搞不清楚哪些基类定义了函数f.假如没有躲藏法则,那么pd->f(10)大概会调用一个出其不意的基类函数f.固然躲藏法则看起来不怎么有原理,但它的确能清除这些不测.
示例8-2-3中,假如语句pd->f(10)一定要调用函数Base::f(int),那么将类Derived改正成以下便可.
class Derived : public Base
{
public:
void f(char *str);
void f(int x) { Base::f(x); }
};
以上是“高质量C++/C编程指南-第8章-C++函数的高级特点(3)[VC/C++编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |