Приведенный выше примерный код не устанавливает отношения между T
и U
.
Один аргумент типа передан шаблону класса myclass
, другой - выводимый тип, переданный конструктору.
Однако, где вы его нашли (в std::shared_ptr
, вероятно), это становится более интересным.
Теперь, в std::shared_ptr
, тело конструктора налагает требование, чтобы U
был потомком от T
. Этот конструктор позволяет создать std::shared_ptr<Base>
от Derived*
, зная внутри конструктора, что он строится из Derived*
.
Зачем нам это нужно? В конце концов, Derived*
может быть преобразован в Base*
вне конструктора, так почему бы не просто взять T*
(aka Base*
)?
Ну, a std::shared_ptr<T>
- это 3 вещи в комплекте. Это T*
, контрольный счетчик и функция очистки («Делетер»).
Когда счетчик ссылок уменьшен до 0, вызывается функция очистки. По умолчанию функция очистки вызывает деструктор объекта с указателем на объект.
Но какой деструктор? Ну, деструктор называется исходя из типа U
, неT
. При построении записывается функция уничтожения, которая знает статический тип U
. Эта функция уничтожения переносится на все копии этого оригинала shared_ptr<T>
, поэтому, даже если он был удален далеко, он все равно вызывает ~U
вместо ~T
.
Если T
имеет virtual ~T()
это не делает много (и на самом деле, одинаковые comdat складывание или подобные методы сделает это ничего не делать), но если он имеет не виртуальный деструктор, shared_ptr
будет вызывать надлежащий деструктор (если тип фактически равен U
, а не некоторый производный тип U
).
shared_ptr
необходимо сохранить функцию уничтожения по другим причинам (вы можете передать пользовательские функции уничтожения), поэтому у этого нет существенных накладных расходов.
Слово не «двойное», оно «вложенное». Вы не можете так называть, вам нужен 'myclass (новый независимо (3));'. То есть вам нужно как-то обеспечить как T, так и U. –
На самом деле вам понадобится 'myclass (new whatever (3));'. Аргументы шаблона класса не могут быть выведены. Какая связь между 'T' и' U' зависит от вашего кода, и я не следую строго из такого простого примера. Я думаю, что это может потребовать, чтобы 'T' был базовым классом' U', но это зависит от того, что представляет собой весь класс. –
zch
Это не должен быть весь класс. 'T' находится где-то в другом месте. – UmNyobe