我有这个代码:
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()
不使用 virtual 关键字。尽管主要代码必须保持不变,但可以更改类。如何才能做到这一点?
(同样,B
源自A
)
我有这个代码:
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()
不使用 virtual 关键字。尽管主要代码必须保持不变,但可以更改类。如何才能做到这一点?
(同样,B
源自A
)
我希望这是出于教育目的。
如果 is 的析构函数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();
}
好吧,你可以做一些乱七八糟的事情,比如将类存储在 A 的实例数据中,并让每个构造函数设置正确的值,并让 A::fun() 检查并适当地转换/重定向。
或者您可以制作自己的虚函数表等价物——和以前一样,它是 A 的实例数据的一部分,但由每个类的构造函数填充。然后,A::fun() 只会做类似 MyTable->Fun() 的事情。
这样的事情可以帮助你。
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();
}