动态绑定子类函数

时间:2016-09-04 17:43:53

标签: c++ dynamic binding

考虑以下代码:

class Bas
{
    public:
        virtual void test() = 0;
};
class Sub : public Bas
{
    public:
        void test(){};
        void subfunc(){};
};
int main()
{
    Bas * bs = new Sub();
    bs->test();
    bs->subfunc(); //Gives error
    return 0;
}

为什么不能在这里使用多态?我的意思是,对象bs是Bas和Sub类型,为什么只能使用Bas中的函数?

4 个答案:

答案 0 :(得分:1)

您只能使用基类指针获取在基类中定义的那些函数。您的基类没有subfunc(),这就是您收到错误的原因。以下代码可能适合您

class Bas
{
public:
    virtual void test() = 0;
    virtual void subfunc(){};
};

class Sub : public Bas
{
public:
    void test(){};
    void subfunc(){};
};

int main()
{
    Bas * bs = new Sub();
    bs->test();
    bs->subfunc();
    return 0;
}

答案 1 :(得分:0)

多态性对subfunc不起作用,因为它不是基类中的虚方法。

Polymorphism (subtyping in this case)仅适用于在基类中重写的虚方法。编译器使用该虚方法为每个类添加一个vtable,以便在运行时调用正确的方法(参见virtual method table)。

向Bas类添加一个没有实现的虚拟子函数。

 class Bas
{
    public:
        virtual void test() = 0;

        virtual void subfunc() = 0; //add this
};

答案 2 :(得分:0)

else { return Fib(n-1)+ Fib(n-2); } 函数中,main已知类型为bs

如果您希望编译器利用其类型Bas(例如调用Sub),您可以将subfunc转发为bs下的Sub确保bs确实具有Sub类型的方法的条件。

class Bas
{
    public:
      virtual void test() = 0;
      virtual bool isSub() const { return false; }
};
class Sub : public Bas
{
    public:
      void test(){};
      virtual bool isSub() const { return true; }
      void subfunc(){};
};
int main()
{
    Bas * bs = new Sub();
    bs->test();
    if (bs->isSub()) {
      assert(dynamic_cast<const Sub*>(bs));
      static_cast<Sub*>(bs)->subfunc();
    }
    return 0;
}

答案 3 :(得分:0)

  

为什么不能在这里使用多态?

subfunc不是virtual,因此在对象的VMT中不存在,因此无法通过基类指针访问它。

  

我的意思是,对象bs是Bas和Sub类型,为什么只能使用Bas中的函数?

对象在内存中可能是Sub,但bs指针指向对象的Bas部分。 C ++是一种类型安全的语言,subfunc中不存在Bas,因此编译器无法通过subfunc指针到达Bas。想想如果bs指向完全不同的派生类对象而不是Sub对象会发生什么:

class Bas
{
    public:
        virtual ~Bas() {}
        virtual void test() = 0;
};

class Sub1 : public Bas
{
    public:
        void test() {};
        void subfunc() {};
};

class Sub2 : public Bas
{
    public:
        void test() {};
        void somethingElse() {};
};

void doTest(Bas *bs)
{
    b->test(); // OK
    b->subfunc(); // error!
    // exists in s1, but not reachable.
    // does not exist in s2 at all.
}

int main()
{
    Sub1 s1;
    doTest(&s1);

    Sub2 s2;
    doTest(&s2);

    return 0;
}

如果编译器在被指向的对象中甚至可能不存在时,您期望它如何调用subfunc

多态性的全部意义在于隐藏实现并仅暴露可调用接口。 subfunc不属于Bas界面。

如果你真的想要调用subfunc,你必须首先确保处理当前的对象类型,然后相应地调整指针以达到它。出于这个目的,C ++有dynamic_cast

void doTest(Bas *bs)
{
    b->test();
    Sub1 *s1 = dynamic_cast<Sub1*>(b);
    if (s1) s1->subfunc();
    Sub2 *s2 = dynamic_cast<Sub2*>(b);
    if (s2) s1->somethingElse();
}