我刚刚尝试了这段代码:
struct FaceOfPast
{
virtual void Smile() = 0;
};
struct FaceOfFuture
{
virtual void Smile() = 0;
};
struct Janus : public FaceOfPast, public FaceOfFuture
{
virtual void Smile() {printf(":) ");}
};..。
void main()
{
Janus* j = new Janus();
FaceOfFuture* future = j;
FaceOfPast* past = j;
future->Smile();
past->Smile();
delete j;
}它可以正常工作(输出两个笑脸),但我认为它甚至不应该编译,在Janus中重新声明Smile()是模棱两可的。
它是如何(以及为什么)工作的?
发布于 2012-04-24 20:05:42
不会有歧义,因为您可以在指向FaceOfFuture和FaceOfPast的指针上调用Smile(),而这些指针只声明了一个方法Smile()。
因为在基类指针上调用该方法不会导致多义性,所以让我们来看看直接在子类指针上调用该方法时的情况
Janus* j = new Janus();
j->Smile();除了覆盖之外,派生类还隐藏了基类的Smile()声明。只有当你不想重写派生类中的方法时,你才会有歧义:
以下代码将进行编译:
struct FaceOfPast
{
virtual void Smile() {printf(":) ");}
};
struct FaceOfFuture
{
virtual void Smile() {printf(":) ");}
};
struct Janus : public FaceOfPast, public FaceOfFuture
{
virtual void Smile() {printf(":) ");}
};
int main()
{
Janus* j = new Janus();
j->Smile();
}尽管您在Janus上调用Smile,但基类声明是隐藏的。
以下内容则不适用:
struct FaceOfPast
{
virtual void Smile() {printf(":) ");}
};
struct FaceOfFuture
{
virtual void Smile() {printf(":) ");}
};
struct Janus : public FaceOfPast, public FaceOfFuture
{
};
int main()
{
Janus* j = new Janus();
j->Smile();
}因为模棱两可。
发布于 2012-04-24 22:38:42
根据C++标准(10.3.2):
如果在类基本和类派生中声明虚拟成员函数vf,则声明具有与<代码>E19基类::vf<代码>E210相同的名称、参数类型列表、cv限定和引用限定符(或缺少相同)的成员函数vf,则<代码>E111派生::vf<代码>E212 ...重写Base::vf。
对于多重继承似乎没有任何特殊的处理,所以它很可能也适用于这里:void Janus::Smile()覆盖了这两个方法,没有任何歧义,只是因为它与两个基类方法具有完全相同的名称和签名。
发布于 2012-04-24 20:48:31
Janus* j = new Janus();
FaceOfFuture* future = j;
FaceOfPast* past = j;这段代码将向下转换为一个基类。因此,当您执行以下操作时
future->Smile();
past->Smile();这实际上是指向FaceofPast和FaceOfFuture的指针。
https://stackoverflow.com/questions/10297405
复制相似问题