Почему чисто виртуальному / абстрактному классу требуется конструктор, в частности для защищенных константных переменных-членов? - PullRequest
4 голосов
/ 22 февраля 2012

У меня есть чисто виртуальный класс, определенный следующим образом:

class BaseClass {
 protected:
  const int var;
 public:
  void somefun() = 0; // what I mean by a purely virtual class
  // stuff...
};

Если я не добавлю конструктор, определенный как такой:

BaseClass(const int & VAR) : var(VAR) {};

, который я должен был бы впоследствии использоватьв любом производном классе мой производный класс не может инициализировать переменную const var в зависимости от того, какое значение он хочет.Теперь я действительно понимаю, что здесь происходит.Перед созданием производного класса вызывается конструктор базового класса, после чего переменные-члены const должны быть инициализированы.Мой вопрос не типа «как заставить мой код работать», это уже сделано.Мой вопрос о том, почему компилятор считает это необходимым.Для чисто виртуального класса, мне не разрешено писать что-то вроде:

class DerivedClass : BaseClass {
 public:
  DerivedClass() : var(SOME_VALUE) {};
}

Если компилятор знает, что за вызовом конструктора BaseClass обязательно последует вызов какого-либо производного класса constructror (поскольку объект абстрактного типа никогда не может быть создан) не должен ли он дать нам немного больше свободы?

Является ли все это следствием того, как C ++ решает проблему Diamond?Даже если бы это было так, не должен ли компилятор хотя бы каким-то образом учесть возможность определения переменной-члена const чисто виртуальных функций в производных классах?Это слишком сложно или это путает с C ++ решением проблемы Diamond?

Спасибо за помощь всем.

Ответы [ 3 ]

5 голосов
/ 22 февраля 2012

Это не «чисто виртуальный» (что бы вы ни имели в виду под этим) - он содержит член данных.

Члены класса могут быть инициализированы только списком инициализатора конструктора этого класса, но не производногоучебный класс.Вот как указывается инициализация объекта: все члены, которые инициализируются, инициализируются до начала тела конструктора.

Постоянные объекты должны быть инициализированы, поскольку им нельзя присвоить значение позже.

Поэтому класс с постоянным элементом данных должен инициализировать его в каждом конструкторе.

2 голосов
/ 22 февраля 2012

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

1 голос
/ 22 февраля 2012

Для чисто виртуального класса мне не разрешено писать что-то вроде

Нет, но вы можете (и в этом случае должны) написать что-то вроде этого:

class DerivedClass : BaseClass {
 public:
  DerivedClass() : BaseClass(SOME_VALUE) {};
};
...