2

我有这个代码:

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

4

3 回答 3

3

我希望这是出于教育目的。

如果 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();
}
于 2012-09-27T11:32:26.487 回答
0

好吧,你可以做一些乱七八糟的事情,比如将类存储在 A 的实例数据中,并让每个构造函数设置正确的值,并让 A::fun() 检查并适当地转换/重定向。

或者您可以制作自己的虚函数表等价物——和以前一样,它是 A 的实例数据的一部分,但由每个类的构造函数填充。然后,A::fun() 只会做类似 MyTable->Fun() 的事情。

于 2012-09-27T11:32:44.700 回答
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();
}

例如http://ideone.com/Zd6cd

于 2012-09-27T11:46:10.327 回答