TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.35K subscribers
Post #415 4.64K
​​Виртуальный конструктор
#новичкам

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

Один из тех самых популярных вопросов на собеседованиях, который не проверяет никаких практически применимых знаний. Он скорее направлен больше на понимание концепции ООП и механизма создания объектов в С++.

Ответ: нет, не можем. Логика тут довольно простая. Виртуальные функции подразумевают собой позднее связывание объекта и вызываемого метода в рантайме. То есть для них нужны объекты(точнее vptr, которых находится внутри них). А объекты создаются в рантайме. И для создания объектов нужны констукторы. Получается, если бы конструкторы были виртуальными, то собака постоянно гналась бы укусить себя за жёпу получился бы цикл и парадокс(фанатам Шарифова посвящается). Нет указателя на виртуальную таблицу - нет виртуальности.

Если более формально и официально, то вот комментарий самого Бъерна по этому вопросу:

A virtual call is a mechanism to get 
work done given partial information.
In particular, "virtual" allows us to
call a function knowing only an interfaces
and not the exact type of the object.
To create an object you need complete
information. In particular, you need to
know the exact type of what you want to
create. Consequently, a
"call to a constructor" cannot be virtual.


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

Однако, нам по сути этого и не нужно. Нам нужен механизм создания объекта, зависящий от типа полиморфного объекта. И у нас такой механизм есть! Называется он фабричным методом. В ту же степь идет и паттерн "метод clone()".

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

Метод clone позволяет создавать объекты именно того класса, который на самом деле лежит под данным указателем или ссылкой.

Выглядит это так:

class Shape {
public:
virtual ~Shape() { } // A virtual destructor
// ...
virtual std::unique_ptr<Shape> clone() const = 0; // Uses the copy constructor
virtual std::unique_ptr<Shape> create() const = 0; // Uses the default constructor
};
class Circle : public Shape {
public:
std::unique_ptr<Shape> clone() const override;
std::unique_ptr<Shape> create() const override;
// ...
};
std::unique_ptr<Shape> Circle::clone() const { return new Circle(*this); }
std::unique_ptr<Shape> Circle::create() const { return new Circle(); }


У класса Фигура есть метод clone, который позволяет скопировать текущий объект в новый объект. Метод create позволяет дефолтно создать объект того же класса.

В класса Circle эти методы переопределяются. Теперь можно не зная точного типа полиморфного объекта вызвать его конструктор по умолчанию и копирования.

std::unique_ptr<Shape> ptr = std::make_unique<Circle>();

auto new_obj = ptr->create();

auto copy_obj = ptr->copy();


В эти методы также можно добавить аргументов, в том числе и полиморфных типов. Главное, чтобы сигнатуры методов в наследниках и базе совпадали.

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

Use well-known tools for your task. Stay cool.

#interview #cppcore #pattern
  • 🔥 24
  • 👍 12
  • ❤ 10
More from @grokaemcpp
  1. Oct 14, 2026​​Что внутри std::condition_variable? #опытным Более менее все знакомы с примитивом синхро…
  2. Oct 12, 2026​​WAT #новичкам Как вы думаете, результат выражения: bool math = -1 < 1U; будет правдой ил…
  3. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  4. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  5. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  6. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →