以下程序由于显而易见的原因而无法编译:
#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内存偏移或只是语法约束?
答案 0 :(得分:4)
这只是表示该函数是纯虚函数的语法。它没有任何实际意义。 C ++设计人员可以选择使用pure
或abstract
代替= 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
创建多个函数,它们的含义仍然相同。