Почему у нас нет виртуального конструктора в C ++? - PullRequest
228 голосов
/ 09 апреля 2009

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

Ответы [ 20 ]

4 голосов
/ 27 ноября 2013

Виртуальные функции используются для вызова функций в зависимости от типа объекта, на который указывает указатель, а не от типа самого указателя. Но конструктор не "вызывается". Он вызывается только один раз, когда объект объявлен. Таким образом, конструктор нельзя сделать виртуальным в C ++.

3 голосов
/ 09 апреля 2009

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

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

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

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

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

3 голосов
/ 09 апреля 2009

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

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

3 голосов
/ 21 сентября 2016

Виртуальная таблица (vtable) создается для каждого класса, имеющего одну или несколько «виртуальных функций». Всякий раз, когда объект создается из такого класса, он содержит «виртуальный указатель», который указывает на базу соответствующего vtable. Всякий раз, когда происходит вызов виртуальной функции, vtable используется для определения адреса функции. Конструктор не может быть виртуальным, поскольку при выполнении конструктора класса в памяти нет vtable, то есть виртуальный указатель еще не определен. Следовательно, конструктор всегда должен быть не виртуальным.

2 голосов
/ 14 апреля 2010

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

2 голосов
/ 18 ноября 2013

Не можем мы просто сказать это как ... Мы не можем наследовать конструкторы. Поэтому нет смысла объявлять их виртуальными, потому что виртуальный обеспечивает полиморфизм.

1 голос
/ 23 июня 2013

C ++ виртуальный конструктор невозможен. Например, вы не можете пометить конструктор как виртуальный. Попробуйте этот код

#include<iostream.h>
using namespace std;
class aClass
{
    public:
        virtual aClass()
        {   
        }  
};
int main()
{
    aClass a; 
}

Это вызывает ошибку. Этот код пытается объявить конструктор виртуальным. Теперь давайте попробуем понять, почему мы используем виртуальное ключевое слово. Виртуальное ключевое слово используется для обеспечения полиморфизма во время выполнения. Например попробуйте этот код.

#include<iostream.h>
using namespace std;
class aClass
{
    public:
        aClass()
        {
            cout<<"aClass contructor\n";
        }
        ~aClass()
        {
            cout<<"aClass destructor\n";
        }

};
class anotherClass:public aClass
{

    public:
        anotherClass()
        {
            cout<<"anotherClass Constructor\n";
        }
        ~anotherClass()
        {
            cout<<"anotherClass destructor\n";
        }

};
int main()
{
    aClass* a;
    a=new anotherClass;
    delete a;   
    getchar(); 
}

В main a=new anotherClass; выделяет память для anotherClass в указателе a, объявленном как тип aClass. Это вызывает автоматический вызов обоих конструкторов (In aClass и anotherClass). не нужно помечать конструктор как виртуальный. Так как при создании объекта он должен следовать цепочке создания (т.е. сначала базовый, а затем производные классы). Но когда мы пытаемся удалить delete a;, он вызывает только базовый деструктор. Поэтому мы должны обработать деструктор с помощью виртуального ключевого слова. Таким образом, виртуальный конструктор невозможен, но виртуальный деструктор . Спасибо

1 голос
/ 24 июля 2015

Существует очень простая причина: конструкторы фактически являются статическими функциями, а в C ++ никакие статические функции не могут быть виртуальными.

Если у вас большой опыт работы с C ++, вы знаете все о разнице между статическими функциями и функциями-членами. Статические функции связаны с КЛАССОМ, а не с объектами (экземплярами), поэтому они не видят указатель «this». Только функции-члены могут быть виртуальными, потому что vtable - скрытая таблица указателей на функции, которая делает «виртуальную» работу - на самом деле является элементом данных каждого объекта.

Теперь, какова работа конструктора? Именно в имени - конструктор "T" инициализирует объекты T по мере их выделения. Это автоматически исключает его функцию-член! Объект должен существовать до того, как у него появится указатель this и, следовательно, vtable. Это означает, что даже если бы язык относился к конструкторам как к обычным функциям (по связанным с этим причинам я не буду вдаваться), они должны были бы быть статическими функциями-членами.

Отличный способ убедиться в этом - взглянуть на шаблон «Завод», особенно на заводские функции. Они делают то, что вам нужно, и вы заметите, что если класс T имеет метод фабрики, он ВСЕГДА СТАТИЧЕСКИЙ. Должно быть.

0 голосов
/ 11 декабря 2017

Если вы логически думаете о том, как работают конструкторы, и каково значение / использование виртуальной функции в C ++, тогда вы поймете, что виртуальный конструктор будет бессмысленным в C ++. Объявление чего-то виртуального в C ++ означает, что оно может быть переопределено подклассом текущего класса, однако конструктор вызывается при создании возражаемого, в то время как вы не можете создавать подкласс класса, вы должны создание класса, чтобы не было необходимости объявлять конструктор виртуальным.

И еще одна причина в том, что конструкторы имеют то же имя, что и его имя класса, и если мы объявляем конструктор как виртуальный, он должен быть переопределен в производном классе с тем же именем, но вы не можете иметь одинаковое имя классы. Поэтому невозможно иметь виртуальный конструктор.

0 голосов
/ 24 сентября 2015

Vpointer создается во время создания объекта. vpointer не существует до создания объекта. поэтому нет смысла делать конструктор виртуальным.

...