我知道这个问题必须无数次被覆盖,但我已经搜索了以前的问题,似乎没有任何问题。
它是关于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
答案 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)