虚继承/多态
Virtual inheritance / Polymorphism
所以我正在研究一些奇怪的多态性案例和
歧义。有一种情况我无法理解。我不明白为什么下面代码的最后一行会这样。
#include <stdio.h>
#include <iostream>
class Article
{
public :
virtual bool compare(Article *a) { std::cout << "ACA" << std::endl;}; // ACA
};
class Clothe : public Article
{
public :
bool compare (Clothe *c) { std::cout << "CCC" << std::endl;}; // CCC
bool compare (Article *a) { std::cout << "CCA" << std::endl;}; // CCA
};
int main()
{
Article *pta1 = new Article;
Article *pta2 = new Clothe;
Clothe *ptv1 = new Clothe;
pta1->compare(pta2); // print ACA
pta2->compare(pta1); // print CCA
pta2->compare(pta2); // print CCA because compiler needs to explore pta2 to determine which compare to use.
// pta2 is instanced as a Clothe, so one of Clothe's compare will be called.
// And judging by its declaration pta2 is an Article (even thought it's instanced as a Clothe),
// so it will Call Clothe::Compare(Article*). I'm OK with this
pta2->compare(ptv1); // print CCA ??? WHY , pta2 is explored, thus it's type is determined to be of type Clothe.
// And ptv1 is declared as a Clothe, so it should call Clothe::compare(Clothe* c)
// should print CCC, shouldn't it ?
}
我迷路了。我不明白 g++ 如何以这种方式解决歧义。
任何帮助/解释都会很好。感谢阅读,更感谢回答的人
PS :我知道比较应该 return bool,但它在这里并不重要。
编辑:在我即时翻译变量名时出现错字,名称最初是法语的,对此深表歉意。现已修复
这一行
pta2->compare(ptv1);
打印CCA
因为基class.
中只有虚函数bool compare(Article *a)
您对 pta2
的假设是错误的。
pta2 is explored, thus it's type is determined to be of type Clothe.
事实并非如此。 pta2
的类型是 Article *
,没有别的。它只指向一个 Clothe
对象,因此可以通过它调用 Clothe
的函数,如果(且仅当)它们存在并且是虚拟的并且基 class 并且被覆盖(具有相同的签名!)在派生的 class.
简单来说:
如果调用是通过基 class 指针执行的,则编译器只能 "find" 在派生 class 中重载,这些重载在基 class 中存在并且是虚拟的。
这里发生了什么:
pta2
是指向 Article
的指针。因此,在调用compare
时,考虑了Article
中compare
函数的不同可能性。
唯一匹配的是bool Article::compare (Article *a)
.
现在编译器发现 Article
中的 compare
是虚拟的,并使用某种内部机制通过对象的 'vtable' 进行虚拟调用。
由于 Clothe
覆盖 bool compare (Article *a)
,被覆盖的函数被调用。
基础class对bool compare (Clothe *c)
一无所知,因为它对Clothe
一无所知,因此输出不是CCV
。
所以我正在研究一些奇怪的多态性案例和 歧义。有一种情况我无法理解。我不明白为什么下面代码的最后一行会这样。
#include <stdio.h>
#include <iostream>
class Article
{
public :
virtual bool compare(Article *a) { std::cout << "ACA" << std::endl;}; // ACA
};
class Clothe : public Article
{
public :
bool compare (Clothe *c) { std::cout << "CCC" << std::endl;}; // CCC
bool compare (Article *a) { std::cout << "CCA" << std::endl;}; // CCA
};
int main()
{
Article *pta1 = new Article;
Article *pta2 = new Clothe;
Clothe *ptv1 = new Clothe;
pta1->compare(pta2); // print ACA
pta2->compare(pta1); // print CCA
pta2->compare(pta2); // print CCA because compiler needs to explore pta2 to determine which compare to use.
// pta2 is instanced as a Clothe, so one of Clothe's compare will be called.
// And judging by its declaration pta2 is an Article (even thought it's instanced as a Clothe),
// so it will Call Clothe::Compare(Article*). I'm OK with this
pta2->compare(ptv1); // print CCA ??? WHY , pta2 is explored, thus it's type is determined to be of type Clothe.
// And ptv1 is declared as a Clothe, so it should call Clothe::compare(Clothe* c)
// should print CCC, shouldn't it ?
}
我迷路了。我不明白 g++ 如何以这种方式解决歧义。 任何帮助/解释都会很好。感谢阅读,更感谢回答的人
PS :我知道比较应该 return bool,但它在这里并不重要。
编辑:在我即时翻译变量名时出现错字,名称最初是法语的,对此深表歉意。现已修复
这一行
pta2->compare(ptv1);
打印CCA
因为基class.
bool compare(Article *a)
您对 pta2
的假设是错误的。
pta2 is explored, thus it's type is determined to be of type Clothe.
事实并非如此。 pta2
的类型是 Article *
,没有别的。它只指向一个 Clothe
对象,因此可以通过它调用 Clothe
的函数,如果(且仅当)它们存在并且是虚拟的并且基 class 并且被覆盖(具有相同的签名!)在派生的 class.
简单来说:
如果调用是通过基 class 指针执行的,则编译器只能 "find" 在派生 class 中重载,这些重载在基 class 中存在并且是虚拟的。
这里发生了什么:
pta2
是指向Article
的指针。因此,在调用compare
时,考虑了Article
中compare
函数的不同可能性。唯一匹配的是
bool Article::compare (Article *a)
.现在编译器发现
Article
中的compare
是虚拟的,并使用某种内部机制通过对象的 'vtable' 进行虚拟调用。由于
Clothe
覆盖bool compare (Article *a)
,被覆盖的函数被调用。
基础class对bool compare (Clothe *c)
一无所知,因为它对Clothe
一无所知,因此输出不是CCV
。