0表示纯虚函数

时间:2013-02-06 12:20:13

标签: c++ constructor pure-virtual

以下程序由于显而易见的原因而无法编译:

#include <iostream>
using namespace std;

class A {
 public:
  A() { pVirt(); }
  virtual void pVirt() const = 0 { count<<"A::pVirt()"; }
};

int main() {
 A aObj;
 aObj.pVirt();
 reutrn 0;
}

问题: 1.签名中的0“virtual void pVirt()const = 0”表示什么?,这是否表示vtable中的NULL内存偏移或只是语法约束?

  1. 如果0是NULL内存偏移量(如果是这样的话)那么为什么VC ++不允许指定另一个内存地址,这就是为什么我们不能从外部构造函数调用纯虚函数的原因(可能是因为vtable是在对象完全构造之后创建的。)?

4 个答案:

答案 0 :(得分:4)

这只是表示该函数是纯虚函数的语法。它没有任何实际意义。 C ++设计人员可以选择使用pureabstract代替= 0。我怀疑不这样做的唯一原因是他们不想在语言中引入新的保留字(因为这会破坏已经使用新保留字作为标识符的任何现有代码)。

(没有必要保留这样的单词,因为它是一个上下文敏感的关键字,但上下文敏感关键字的概念最近才进入主流使用,而且这种语法要老得多。)

答案 1 :(得分:4)

  签名中的

0“virtual void pVirt()const = 0”表示什么?,

部分=0称为纯说明符。它使虚拟函数,并使类抽象

纯虚函数不需要定义。您可以选择在类外提供定义,而非抽象派生类必须覆盖该函数。

class A
{
 public:
     virtual ~A() {};
     virtual void f() =0;
};

void A::f() { std::cout << "A::f" << std::endl; } //optional

f的定义不会使该类非抽象,因此您无法创建A的实例:

A a; //error - A is abstract

此外,派生类必须覆盖A::f才能成为非抽象:

class B : public A {};

B b; //error : B is still an abstract class as it didn't override A::f

并且

class C : public A { void f() {} };

C c; //okay : C override A::f

派生类实现可以选择调用基类实现:

class D : public A { void f() {  A::f(); } }; //defaults to A::f

D d; //okay : D override A::f, but calls A::f internally

希望有所帮助。

答案 2 :(得分:2)

函数声明中的= 0只是语法:两者 令牌序列意味着该功能是纯粹的,就是全部。和 你不能用其他任何东西替换任何一个令牌:例如,= 0L是不合法的。

你得到错误的原因只是因为 语法是不允许的。由于历史原因,如果没有别的。 如果要为纯虚函数提供定义, 你必须在课外做。

if if 为纯虚函数提供定义, 你可以从构造函数中调用它;你只需要 停用虚拟呼叫机制;例如A::pVirt()。如果 实际的函数调用涉及动态分辨率,以及 分辨率导致纯虚函数,它是未定义的 行为,无论是否定义了函数。 这里的动机是让你不要定义它;一般, 必须定义一个虚函数,无论你是否调用它, 因为编译器必须将其地址放在vtable中,并且 如果没有定义,则没有地址。制作功能 pure virtual告诉编译器它不应该放入它 vtable中的地址。所以你不必定义它。但 如果你试图调用该功能,你可能会感到惊讶 vtable。

答案 3 :(得分:1)

虚函数后的= 0表示“这是纯虚函数,必须在派生函数中实现”。在您的示例中,仍然可以实现该功能。它没有其他含义 - 你不能使用其他数字,地址或其他任何东西。您可以使用=0创建多个函数,它们的含义仍然相同。