我有这段代码:
A * a = new A;
a->fun();
delete a;
a = new B;
a->fun();
delete a;
我需要做的是打印:
A::fun() //being printed by A's fun()
B::fun() //being printed by B's fun()
没有使用虚拟关键字。虽然主代码必须保持不变,但可以更改类。怎么办呢?
(另外,B
派生自A
)
答案 0 :(得分:3)
我希望这是出于教育目的。
如果a
的析构函数不是virtual
,则会导致未定义的行为。所以析构函数必须是virtual
。
如果析构函数为virtual
,则可以使用dynamic_cast
。因此,您可以将A::foo
更改为:
void A::fun()
{
if ( dynamic_cast<B*>(this) )
((B*)this)->fun();
else
std::cout << "A::fun()";
}
virtual
析构函数(如果调用delete
,则为未定义的行为):struct A
{
bool isA;
A(bool isA = true) : isA(isA){};
void fun();
};
struct B : A
{
B() : A(false){}
void fun() {cout<<"B::fun()"<<endl;}
};
void A::fun()
{
if (isA)
std::cout << "A::fun()"<<endl;
else
((B*)this)->fun();
}
答案 1 :(得分:0)
好吧,你可以做一些凌乱的事情,比如将类存储在A的实例数据中,让每个构造函数都设置正确的值,并使A :: fun()检查并适当地投射/重定向。
或者您可以创建自己的虚函数表 - 与之前相同,它是A的实例数据的一部分,但是由每个类的构造函数填充。然后,A :: fun()只会做类似MyTable-&gt; Fun()的事情。
答案 2 :(得分:0)
这样的事情可以帮到你。
class B;
class A
{
public:
A() : instance(0) { }
A(B* p): instance(p) { }
virtual ~A() { }
void foo();
private:
B* instance;
};
class B : public A
{
public:
B():A(this) { }
void foo() { std::cout << "B::foo" << std::endl; }
};
void A::foo()
{
if (!instance)
{
std::cout << "A::foo" << std::endl;
return;
}
instance->foo();
}