关于dynamic binding及static binding的思考
先看个例子:
- C/C++ code
class A{ public: virtural void fun( void ){ cout << "A"; return; }};class B : public A{ public: virtual void fun( void ){ cout << "B"; return; }};int main( void ){ A* p = new B; p -> A::fun( ); return 0;}
A::fun( )这个叫虚拟函数的静态解析。这是近日在回答一个问题时的类似代码,原来偶对这个问题是比较确定的,但后来细细斟酌,却也未必。问题是:虚拟函数的静态解析属于dynamic binding还是static binding??
有些人可能毫不迟疑地认为应该是static binding,因为对于static binding,一般的定义是编译期确定;但是,对照C++标准,却也未必,C++标准是这样说的:
[Note: the interpretation of the call of a virtual function depends on the type of the object for which it is
called (the dynamic type), whereas the interpretation of a call of a nonvirtual member function depends
only on the type of the pointer or reference denoting that object (the static type) (5.2.2). ]
C++标准明确说了虚拟函数调用是依赖动态类型的,这里并没有加上对qualified-id的例外。那么,按照这个条款,A::fun()也是根据动态类型解析的,解析的目标是找到final overrider,方法是member name lookup:
10.3 Virtual functions
.............Then in any well-formed class, for each virtual function declared in that class or any of its direct or indirect base classes there is a unique final overrider that overrides that function and every other overrider of that function. The rules for member lookup (10.2) are used to determine the final overrider for a virtual function in the scope of a derived class but ignoring names introduced by using-declarations.
这个member name lookup是怎样的呢?C++标准是这样描述的:
10.2 Member name lookup
.........For an id-expression, name lookup begins in the class scope of this; for a qualified-id, name lookup begins in the scope of the nested-name-specifier.
上述fun就是一个id-expression,这个条款明确地规定对于一个qualified-id(这个例子中的A::fun),名称搜索从嵌套名称指示符(nested-name-specifier)开始。
也就是说,qualified-id的名称搜索总体上依然属于虚拟函数dynamic binding的搜索方法范畴,但是方法中的一个分支。
于是,这个语义就跟static binding的语义有冲突了,A::fun()是属于dynamic binding呢,还是static binding?这个问题耐人寻味,如果说是C++03标准尚未考虑到的情况,但C++11并没有进行修改。BS、lippmen也没有对这个问题有明确的说明。
欢迎大家踊跃发表看法!
[解决办法]
static binding
p -> A::fun()的语义是 以p做对象指针 调用 A::fun函数.
明确指明了调用 类A的fun 函数, 无论fun是不是虚函数.
所以这个地方的搜索范围就限定了 A::fun,
如果类A没有fun,则搜寻其基类.
不可能根据虚函数去动态调用B::fun,
因为B::fun 不是类A的函数.
[解决办法]
学习了~
[解决办法]
因为当年gcc的3个版本给出了x->y->x式的答案变化。
[解决办法]
我觉得是static binding
[解决办法]
[解决办法]
那个,y是VC的一贯输出。所以,说是gcc的bug轻率了点,说和标准没关系,则极可能太托大自己了。
[解决办法]
[解决办法]
我貌似记得mayers反复教导我们,不要轻言自己或者编译器错了。
gcc的作者们,可能哪个都比我们更认真研究过标准的原文。
[解决办法]
[解决办法]
[解决办法]
当然应该是静态绑定的.
即使标准里面有些许文字和这个语义冲突,也不应该去咬文嚼字,要从整体上领略其设计原则。标准也是人订的,是人都可能犯错,谁能保证那么大的一个文案里面每一个脚注都面面俱到?
对于虚函数调用(the call of a virtual function)来说,加 A:: 这样的限定词是没有任何意义的,虚函数用的是运行时的对象的动态信息。而像 A:: 这样的类型信息是编译时的,在运行时已经不存在了。 如果把 p->A::fun( ); 按动态绑定来处理,那里面的 A:: 没有任何意义, C++ 就应该禁止这种语法。
而另一方面,即使是虚函数,也有直接调用它的需求. C++ 要满足这种需求,必须提供某种语法来支持,显然 p->A::fun() 正是为此而设计的。