从超类调用子类中的虚函数

时间:2010-08-22 09:18:28

标签: c++ inheritance virtual

我知道这个问题必须无数次被覆盖,但我已经搜索了以前的问题,似乎没有任何问题。

它是关于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 *。

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

当我这样做,并在myObject上调用foo()时,A :: foo()调用bar()。但是只调用B :: bar(),而不是C :: Bar() - 实际上是myObject,即使它被声明为B,它再次影响“//什么也不做”不会被执行。

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

有道理吗?

// Trenskow

编辑:

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

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

像这样:

void A:Foo(void *a) {

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

}

现在编译器认为,tmpA是A.但不知怎的,它设法确定它是B *,并且调用B :: Bar,实际上tmpA是C *并且它应该调用C :: Bar

6 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分:2)

void A:Foo(void *a) {

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

}

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

答案 2 :(得分:0)

假设您错误输入了最后一段代码并且名称匹配:

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

然后调用C :: Foo方法,或者你正在使用一个非常糟糕的编译器。

(这也假设您在C :: Foo中实际上没有编译器错误,并且注释实际上类似于std::cout << "Hi mom!" << std::endl;

答案 3 :(得分: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'。

答案 4 :(得分:0)

我不跟随。你说的是

  

但只调用B :: bar(),而不是   Ç:: bar()的

没有。你调用了类C的构造函数,这意味着vtable使bar()指向C :: bar(),所以在这种情况下调用foo()将直接转到C :: bar()。

如果你想强制A :: foo()明确地只调用A的实现,你可以通过写

来做到这一点。
void foo() { A::bar(); }

你究竟想做什么?

答案 5 :(得分:0)

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