2010-08-22 68 views
5

我知道这个问题必须被覆盖无尽的时间,但我已经搜索了以前的问题,没有任何东西似乎弹出。在超类的子类中调用虚函数

这是关于继承和虚函数我C++。我在调用超类的子类中的虚函数时遇到了问题。

让我举个例子。从三个类开始,它们相互继承。

class A { 

    void foo() { bar() } 
    virtual void bar() { } 

}; 

class B : public A { 

    virtual void bar() { } 

}; 

class C : public B { 

    virtual void bar() { // do something } 

}; 

现在我想要一个声明为B *的变量,但实例化为C *。当我这样做,并在myObject上调用foo(),然后A :: foo()调用bar()。但是只调用B :: bar(),而不是C :: Bar() - 实际上myObject是这样的,即使它被声明为B,这又会影响“//不做任何事”不会被执行。

我该如何告诉A :: foo(),它需要看最低的实现?

有意义吗?

// Trenskow

编辑:

Ç:: foo是没有问题的。 Foo被称为A级,因为它是唯一实施的地方。问题出现时,A:Foo调用Bar()。然后B:Bar被调用,而不是C :: Bar。

也许问题是,在我的实现,我只得到一个void *指针对象A.

像这样:

void A:Foo(void *a) { 

    A* tmpA = static_cast<A*> (a); 
    tmpA->bar(); 

} 

现在,编译器认为,这TMPA是答:但不知何故,它设法确定它是一个B *,并且调用B :: Bar,实际上tmpA是一个C *,它应该调用C :: Bar。

+1

如果你发布了真实的代码,那么我们可以告诉问题是。你不需要做任何特别的事情。如果语法错误得到解决,代码('myObject-> foo();')将调用'C :: bar()'。 – UncleBens 2010-08-22 09:23:20

+0

......但是如果我猜测,要么'C'并没有真正覆盖'bar'(具有不同的签名),或者你在某处切分对象(通过执行诸如'* variable = * myObject;' – UncleBens 2010-08-22 09:33:21

+0

我仍然不会购买它,为什么不调用C :: bar()?你能发布实际的代码吗? – EboMike 2010-08-22 09:43:17

回答

5

下面按预期显示“A :: foo C :: bar”。你有不同的东西吗? B::bar永远不会被调用,因为C是对象的实际运行时类型。在C::bar中,您可以通过在其正文中添加B::bar();明确地呼叫B::bar

#include <iostream> 
using namespace std; 

class A { 
public: 
    void foo() { cout << "A::foo "; bar(); } 
    virtual void bar() { } 
}; 

class B : public A { 
public: 
    virtual void bar() { cout << "B::bar" << endl; } 
}; 

class C : public B { 
public: 
    virtual void bar() { cout << "C::bar" << endl; } 
}; 

int main() 
{ 
    B* c = new C(); 
    c->foo(); 
    return 0; 
} 
0

假设输入错误的代码的最后一块的名称相匹配:

B* variable = new C(); 
variable->foo(); 

那么C :: Foo中的方法被调用,或者你使用非常糟糕的编译器。

(这还假定你实际上并不在C ::美孚编译器错误,并且该评论确实是一样的东西std::cout << "Hi mom!" << std::endl;

0

你不是说:

B* myObject = new C(); 
myObject->foo(); // not variable->foo() 

class A 
{ 
public: 
    void foo() { bar(); } 
    virtual void bar() { std::cout << "A"; }; 
}; 

class B : public A 
{ 
public: 
    virtual void bar() { std::cout << "B";}; 
}; 

class C : public B 
{ 
public: 
    virtual void bar() { std::cout << "C"; } 
}; 

按预期打印“C”。

+0

哦,拍摄是啊。在编辑中更改变量名称,而不是将其称为变量。必须忘记第二行。编辑 – Trenskow 2010-08-22 09:38:47

0

我不关注。你说

但只有B ::巴()被调用,而不是 Ç::酒吧()

号你调用C类的构造函数,这意味着V表使bar()指向C :: bar(),所以在这种情况下调用foo()会直接到C :: bar()。

如果要强制A :: foo的()明确只调用的实现,你可以做到这一点仅通过写

void foo() { A::bar(); } 

究竟是你想做些什么?

0

你使用什么编译器? Visual Studio(IIRC)通常默认关闭运行时类型信息,所以它可能就是这么简单?

2
void A:Foo(void *a) { 

    A* tmpA = static_cast<A*> (a); 
    tmpA->bar(); 

} 

这是未定义的行为。你不能将B *转换为void *,然后将该void *转换回A *。如果你想让它正常工作,你必须抛弃void *。或者,您可以尝试dynamic_cast。

+0

或者您先将B *转换为A *,然后将A *转换为void *。 – Tomek 2010-08-22 18:03:36