【C/C++】关于C++的名字查找与继承
为了将问题简化,首先来看一段代码:
#include <tchar.h> #include "stdio.h" class A { public: void func() { printf("A::func\n"); } }; class B : public A { public: void func(int n) // 注意这里func与A的func同名,但参数不同 { printf("B::func\n"); } }; int _tmain(int argc, _TCHAR* argv[]) { B b; b.func(); // 期望调用B的基类A的func()函数 return 0; }
这里本来是期望调用A::func()函数,但很抱歉,编译器不会如您所愿,编译器会报错:
1>f:\testproj\consoletest_vs2005\test\test.cpp(25) : error C2660: 'B::func' : function does not take 0 arguments
这是什么原因呢?翻阅C++ Primer可以得到答案:
C++ Primer 中文第四版P500的注解:如果派生类重定义了重载成员,则通过派生类型只能访问派生类中重定义的那些成员。
为什么会这样?要理解这个问题就需要知道了解C++中名字查找与继承(C++ Primer 中文第四版P501的关键概念):
确定函数调用遵循以下四个步骤:
1.首先确定进行函数调用的对象、引用或指针的静态类型。
2.在该类中查找函数,如果找不到,就在直接基类中查找,如此循着类的继承往上找,直到找到该函数或者查找完最后一个类。如果不能在类或其相关基类中找到该名字,则调用是错误的。
3.一旦找到了该名字,就进行常规类型检查(7.1.2节),查看如果给定找到的定义,该函数是否合法。
4.假定函数合法,编译器就生成代码。如果函数是虚函数且通过引用或指针调用,则编译器生成代码以确定根据对象的动态类型运行哪个函数版本,否则,编译器生成代码直接调用函数。
以上就是这个问题的解释。