心寄笔端 附庸风雅

甘草的技术博客

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

昨天和一个群(Rust)友聊天,大家讨论静多态,动多态,然后一个朋友说静多态实现是基于重载的。后来我们还私聊了半天,他总是问我“模板结果就是重载!”,承认不承认。

首先,我的观点是,重载不算是多态。第二,我当时不理解他说的模板结果就是重载的含义(所以不能轻易说承认,或者否认),然后他多次提到this指针的实现:实际上是函数调用的一个参数。

后来我想明白他的逻辑了:...是这样的,咱们进入正题。

A : C<A> 省略一切和问题无关的语言要素,例如public修饰等等。

B : C<A>

这里A和B是两个无关的类,不存在父子关系。然后静多态是在基类C 类模板中进行的调用的(这是大家都知道的了),问题就在于A::f(1) 和 B::f(1)的调用上。

我想明白他的逻辑是这样的:

A::f(1) 基本等效于 f( (A*)pThis, 1); 【这就算是个人人共知的事情吧,】

那么B::f(1)就是     f( (B*)pThis, 1 );了。

那么 f( (A*)pThis, 1)和  f( (B*)pThis, 1 );当然是重载的关系了。

-------------------------------------------------------------------------------------------------------------

这个应该就是他的理论基础了。所以我现在给出明确的回答好了,  模板结果就是重载 是 错误的!

模板结果就是重载 是 错误的! 模板结果就是重载 是 错误的!(知乎体)

再次进入论证,

1. 正面的证明就是,C++定义overload函数,有明确的说明,函数同名,且在一个Scope内。

参看【http://stackoverflow.com/questions/429125/override-and-overload-in-c】里面说,Overloading generally means that you have two or more functions in the same scope having the same name.

所以,A::f(int)和B::f(int)根据定义就不是互为重载的。至于,this指针也是一个参数,这个只是帮助初学者理解this的一个办法,然而二者并不是等价的。

1.1 二者当然不是等价的了【证明二者不是等价的】

a->f(1);

f(a, 1);

是不等价的,前者是有可能发生动多态调用的,而后者的写法,是怎么都不会发生这个动多态调用的情况的,所以你理解的【A::f(1) 基本等效于 f( (A*)pThis, 1)】只是一个理解。

1.2 当然,你可能还是觉得不服气,觉得在实现上,就是等价的,就是基于重载的。

那么按照你的等价观点,max(int, int)和std::max(int, int)也是互为重载的,但是显然不是啊。

2. 反面的证明(就是你说的反证)

首先,C++编译一个函数,是有一个固定的顺序的, 1) Name Look Up(命名查找),2) Resolution (重载决议) 3) 可访问性检查

那么:当你调用a->f(1, 2); 就会先发生命名查找,

然后:如果A::f(int)和B::f(int)互为重载函数的话,那么A::f(int)和B::f(int, int)也就互为重载了。【这个推论是显而易见的吧?】

那么结果应该是A范围内找到f(int)函数,B范围内找到f(int, int),然后进行重载决议。然而,第一个参数类型是不匹配的。编译器就会报你们写重载函数类型不匹配的编译错误。

然而,结果将是编译报错,说找不到f(int, int)。

也就是说,命名查找这关就过不去,而不是重载决议过不去。因为A::f(...)和B::f(...)就不是重载函数。

 

所以,根据正反两种证明,模板结果就是重载 是 错误的!

写在最后,A::f(1) 基本等效于 f( (A*)pThis, 1),只是在某些情况下便于你理解this,然而不是在任何时候都是正确的。否则max, std::max, boost::max, ClassA::max不都是重载了吗? (呵呵)

posted on 2015-07-07 10:41  甘草  阅读(296)  评论(0编辑  收藏  举报
Baidu
Google
心寄笔端
TEST
以后我会加上Power By的,先别介意