Почему у нас нет виртуального конструктора в C++?

Вам нужно сохранить ссылку на связанную функцию, чтобы с ней позже можно было вызвать removeEventListener:

const boundHandler = handler.bind(null, name, callback);
document.addEventListener(name, boundHandler, false);

// later:

document.removeEventListener(name, boundHandler, false);
239
задан nitin_cherian 5 February 2012 в 21:38
поделиться

9 ответов

В отличие от объектно-ориентированных языков, таких как Smalltalk или Python, где конструктор представляет собой виртуальный метод объекта, представляющего класс ( это означает, что вам не нужен шаблон абстрактной фабрики GoF , поскольку вы можете передавать объект, представляющий класс, вместо создания собственного), C ++ является языком на основе классов и не имеет объектов, представляющих какие-либо объекты. языковых конструкций. Класс не существует как объект во время выполнения, поэтому вы не можете вызывать для него виртуальный метод.

Это соответствует философии «вы не платите за то, что вы не используете», хотя каждый большой C ++ Проект, который я видел, закончился реализацией некой формы абстрактной фабрики или рефлексии.

59
ответ дан Pete Kirkham 23 November 2019 в 03:19
поделиться

Услышь это изо рта лошади. :)

Из часто задаваемых вопросов Бьярна Страуструпа по стилю и технике C ++ Почему у нас нет виртуальных конструкторов?

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

Запись FAQ продолжает давать код для способа достижения этой цели без виртуального конструктора.

227
ответ дан Marc.2377 23 November 2019 в 03:19
поделиться

Когда люди задают такой вопрос, мне нравится думать себе: «Что бы произошло, если бы это было на самом деле возможно? " Я на самом деле не знаю, что это будет значить, но я думаю, что это как-то связано с возможностью переопределить реализацию конструктора, основанную на динамическом типе создаваемого объекта.

Я вижу ряд потенциальных проблем с это. С одной стороны, производный класс не будет полностью сконструирован во время вызова виртуального конструктора, поэтому существуют потенциальные проблемы с реализацией.

Во-вторых, что произойдет в случае множественного наследования? Вероятно, ваш виртуальный конструктор будет вызываться несколько раз, тогда вам нужно будет каким-то образом узнать, какой из них вызывается.

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

Наконец, как заметил кто-то другой, вы можете реализовать своего рода виртуальный конструктор, используя статический «create». Функции типа "or" init ", которые в основном делают то же самое, что и виртуальный конструктор.

5
ответ дан 1800 INFORMATION 23 November 2019 в 03:19
поделиться

Вы также не должны вызывать виртуальные функции внутри вашего конструктора. См. http://www.artima.com/cppsource/nevercall.html

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

3
ответ дан Edouard A. 23 November 2019 в 03:19
поделиться

Да, это просто не конструктор: -)

struct A {
  virtual ~A() {}
  virtual A * Clone() { return new A; }
};

struct B : public A {
  virtual A * Clone() { return new B; }
};

int main() {

   A * a1 = new B;
   A * a2 = a1->Clone();    // virtual construction
   delete a2;
   delete a1;
}
13
ответ дан 23 November 2019 в 03:19
поделиться

Виртуальные функции в основном обеспечивают полиморфное поведение. То есть, когда вы работаете с объектом, динамический тип которого отличается от статического (время компиляции) типа, к которому он относится, он обеспечивает поведение, соответствующее фактическому типу объекта вместо статический тип объекта.

Теперь попробуйте применить такое поведение к конструктору. Когда вы создаете объект, статический тип всегда совпадает с фактическим типом объекта, поскольку:

Для создания объекта конструктору нужен точный тип объекта, который он должен создать [...] Более того [... ] у вас не может быть указателя на конструктор

(Бьярн Страуступ (P424 Язык программирования C ++ SE))

125
ответ дан Anton Gogolev 23 November 2019 в 03:19
поделиться

две причины, по которым я могу придумать:

Техническая причина

Объект существует только после завершения конструктора. По порядку для отправки конструктора с использованием виртуальной таблицы должен существовать объект с указателем на виртуальную таблицу, но как может существовать указатель на виртуальную таблицу, если объект еще не существует? : )

Логическая причина

Вы используете ключевое слово virtual, когда хотите объявить несколько полиморфное поведение. Но в конструкторах нет ничего полиморфного, задача конструкторов в C ++ - просто поместить объектные данные в память. Поскольку виртуальные таблицы (и полиморфизм в целом) имеют дело с полиморфным поведением, а не с полиморфными данными, объявлять виртуальный конструктор бессмысленно.

40
ответ дан 23 November 2019 в 03:19
поделиться

Семантические причины в сторону , vtable не существует до тех пор, пока объект не будет построен, что делает виртуальное обозначение бесполезным.

14
ответ дан 23 November 2019 в 03:19
поделиться

Виртуальный механизм работает только при основе указателя класса на производный объект класса. Конструкция имеет свои собственные правила для вызова конструкторов базового класса, в основном базового класса для производного. Как виртуальный конструктор может быть полезен или вызван? Я не знаю, что делают другие языки, но я не вижу, как виртуальный конструктор может быть полезен или даже реализован. Строительство должно иметь место, чтобы виртуальный механизм имело какой-либо смысл, и строительство также должно иметь место для создания структур vtable, которые обеспечивают механику полиморфного поведения.

1
ответ дан 23 November 2019 в 03:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: