是否在重载分辨率中实际选择了纯虚函数?

时间:2014-07-25 17:05:34

标签: c++

来自我在上一个问题中的评论:

  

由于不能有抽象类的实例,因此在重载解析后永远不能选择纯虚函数

明显的反应是:

abstract_class* a = new derived_class; a->pure_virtual_function();

以及正确性的最佳证明:

  

动态调度在运行时发生,基于当时实际使用的对象。重载解析在编译时发生。


然而令我烦恼的是,当在我们的情况下明确地解析类成员的范围时,编译失败,所以看起来pure virtual function从未通过重载解析实际选择:< / p>

struct B
{
    virtual void copy(B const& rhs) = 0;
};

struct D : B
{
    void copy(B const& rhs)
    {
        D const *pd = dynamic_cast<D const*>(&rhs);
        if (pd) {
            y = pd->y;
        }
    }
    int y;
};

int main()
{
    D d1, d2; 
    d1.y = 2;
    d2.y = 5;

    B *p1(&d1), *p2(&d2); 

    ////////////////////////////////////////////
    (*p1).B::copy(*p2);
    ////////////////////////////////////////////

    return 0;
}

错误消息

  

未定义引用`B :: copy(B const&amp;)'

Demo

这里的情况是什么,如果在重载决策中实际选择了纯虚函数,为什么我不能“强迫”编译器执行相同的操作(如解析所做的那样)。

2 个答案:

答案 0 :(得分:2)

可以通过重载分辨率选择纯虚函数。在大多数情况下,它不会被调用。它的最终覆盖将被调用,就像任何其他虚函数一样。

struct A
{
  virtual void foo() = 0;
  void foo(int);
};

A* getA();

int main ()
{
   A* a = getA();
   a->foo();
}

struct B : A
{
  void foo() {}
};
A* getA()
{
  return new B;
}

重载分辨率在编译时选择A::a() B::a()),然后在运行时找到B::a()并由虚拟调度机制调用。纯度与此无关。

答案 1 :(得分:1)

如果我理解,你真的有两个问题。两者都在这里解决:

为什么编译失败?

失败是因为您明确尝试调用没有实现的纯虚函数。但是,可以实现纯虚函数。这是一个单行实现,它将使您的代码成功编译并运行:

void B::copy(B const& rhs) { std::cout << "I am pure and virtuous\n"; }

是否在重载分辨率中实际选择了纯虚函数?

总之,不,不是在这种情况下。但是有一种情况是必须实现纯虚函数并且被调用(但严格来说,不是由于重载决议)。那种情况是存在基类的纯虚析构函数。有关原因和方式的详细信息,请参阅this SO question

但是,可以在重载决策中选择纯虚函数 。将其添加到B

void B::copy(B const& rhs) const { std::cout 
         << "I am pure and virtuous and constant\n"; }

D中的相应功能:

void copy(B const& rhs) const { /* do nothing */ }

您会发现重载分辨率只会导致“我纯洁而善良”。