我可以从基类指针访问派生类的非虚函数吗?

时间:2012-09-27 11:26:33

标签: c++ inheritance polymorphism virtual

我有这段代码:

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

3 个答案:

答案 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();
}

示例http://ideone.com/Zd6cd