【问题标题】:What are the semantics of a virtual abstract method?虚拟抽象方法的语义是什么?
【发布时间】:2018-05-23 13:22:47
【问题描述】:

根据用户 Steve314Why do we need virtual functions in C++? 上的回答引用:

使用“虚拟”可以获得“后期绑定”。使用该方法的哪个实现在运行时根据指向对象的类型来决定——它最初被构造为什么。根据指向该对象的指针的类型,这不一定是您的想法。

我偶然发现了以下示例:

class Shape
{
    std::string name;
    friend std::ostream& operator<<(std::ostream&, const Shape&);
public:
    Shape(const std::string&);
    virtual double circumference() = 0; 
    virtual ~Shape() {}
protected:
    virtual void print(std::ostream&) const;
};

在继承自 Shape 的类(例如 Circle、Square...)中,虚函数被覆盖。方法圆周()就是这种情况。

我的问题如下:如果圆周()是一个不能调用的抽象方法(因为Shape是一个抽象类),为什么我们要把它变成一个虚函数而不是简单地让它保持抽象并像往常一样覆盖它在派生类中?

如果我理解正确,我们会创建一个方法virtual 来确保“后期绑定”。例如。如果我们有以下代码块:

Shape *circle = new Circle();
double circ = circle->circumference();

通过将圆周()设为虚拟,我们确保将调用我们指向的对象的类类型的方法,而不是“声明”类型的方法(这里我们要调用 Circle 类的方法)。

那么,如果以任何方式调用 Shape 类的 circle() 会导致编译时错误(使其不可能发生),为什么我们将其设为虚拟而不只是抽象呢?

【问题讨论】:

  • “是虚拟的而不只是抽象的?” 因为virtual= 0;的组合正是如何使函数抽象
  • 只有虚函数可以是抽象的。非虚函数不能被覆盖。

标签: c++ inheritance


【解决方案1】:

附加了= 0virtual 方法是抽象方法的定义。没有virtual 关键字就没有抽象方法。

double circumference() = 0; 

这只是一个语法错误。非virtual 方法必须有定义。不能抽象,有= 0

这样想:

  1. 该方法是否需要后期绑定,以便调用的确切实现在运行时会有所不同?如果是这样,请将其标记为virtual
  2. 如果是virtual,基类是否要提供默认实现?如果没有,则添加= 0

没有第 1 步,就无法进行第 2 步。

【讨论】:

  • 我认为您提供的代码制作抽象函数的方法。原来虚拟+纯=抽象。 stackoverflow.com/questions/6574852/… 仍然让我感到困惑,abstract 方法的概念如何与引用文本中描述的 virtual 语义相匹配。
  • "如果是virtual,基类是否要提供默认实现?如果没有,则添加= 0" 抽象方法可以有默认实现执行。通常不这样做,但允许这样做。将方法标记为抽象只是意味着它必须被覆盖。但是,如果重写方法有默认实现,则可以调用基类抽象方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-18
  • 1970-01-01
  • 2010-10-11
  • 2014-03-18
  • 1970-01-01
  • 2014-12-24
  • 1970-01-01
相关资源
最近更新 更多