Что означает 0 в чистой виртуальной функции

Программа ниже не компилируется по понятным причинам:

#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" означает что?, Это указывает на смещение памяти NULL в vtable или просто ограничение синтаксиса?

  1. Если 0 - это NULL смещение памяти (если это так), то почему VC++ не позволяет указывать другой адрес памяти, и именно поэтому мы не можем вызывать чисто виртуальную функцию извне конструктора (МОЖЕТ БЫТЬ, потому что vtable создан после того, как объект полностью построен.)?

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

Надеюсь, это поможет.

Это просто синтаксис для обозначения того, что функция является чисто виртуальной. Это не имеет никакого реального значения вообще. Дизайнеры C++ также могут быть выбраны для использования pure или же abstract на месте = 0, Я подозреваю, что единственная причина этого не состояла в том, что они не хотели вводить новое зарезервированное слово в язык (поскольку это нарушает любой существующий код, который уже использует вновь зарезервированное слово в качестве идентификатора).

(Не нужно делать такое слово зарезервированным, так как это будет контекстно-зависимое ключевое слово, но концепция контекстно-зависимых ключевых слов только недавно вошла в массовое использование, и этот синтаксис намного старше.)

= 0 в объявлении функции просто синтаксис: последовательность из двух токенов означает, что функция чистая, вот и все. И вы не можете заменить ни один из токенов чем-либо еще: = 0L не законно, например.

И причина, по которой вы получаете ошибку, заключается просто в том, что синтаксис не разрешен. По историческим причинам, если не больше. Если вы хотите предоставить определение для чисто виртуальной функции, вы должны сделать это вне класса.

И если вы предоставите определение для чисто виртуальной функции, вы можете вызвать ее из конструктора; вам просто нужно отключить механизм виртуального вызова; например A::pVirt(), Если фактический вызов функции включает в себя динамическое разрешение, и разрешение приводит к чисто виртуальной функции, это неопределенное поведение, независимо от того, определена функция или нет. Мотивация здесь состоит в том, чтобы позволить вам не определять это; обычно виртуальная функция должна быть определена независимо от того, вызываете вы ее или нет, потому что компилятор должен поместить ее адрес в vtableи, если он не определен, адрес отсутствует. Создание функции чисто виртуальной говорит компилятору, что она не должна помещать свой адрес в vtable, Так что вам не нужно это определять. Но вы можете получить сюрпризы, если попытаетесь вызвать функцию через vtable.

= 0 после того, как виртуальная функция означает, что "это чисто виртуальная функция, она должна быть реализована в производной функции". Как и в вашем примере, все еще возможно реализовать функцию. У него нет другого значения как такового - и вы не можете использовать другие номера, адреса или что-то еще. Вы можете иметь несколько функций с =0и это все равно будет иметь тот же смысл.

Другие вопросы по тегам