Я слышал, что шаблоны функций-членов класса C ++ не могут быть виртуальными. Это правда?
Если они могут быть виртуальными, то каков пример сценария, в котором можно использовать такую функцию?
c++
templates
virtual-functions
function-templates
c++-faq
WannaBeGeek
источник
источник
Ответы:
Шаблоны - это все о генерации кода компилятором во время компиляции . Виртуальные функции - это система времени выполнения, которая определяет, какую функцию вызывать во время выполнения .
Как только система времени выполнения выяснила, что ей нужно будет вызвать виртуализированную виртуальную функцию, компиляция завершена, и компилятор больше не может генерировать соответствующий экземпляр. Поэтому у вас не может быть шаблонов виртуальных функций-членов.
Тем не менее, есть несколько мощных и интересных методов, вытекающих из сочетания полиморфизма и шаблонов, в частности, так называемое стирание типов .
источник
Virtual functions are all about the run-time system figuring out which function to call at run-time
- извините, но это довольно неправильный путь и довольно запутанный. Это просто косвенное обращение, и в нем не задействовано «выяснение времени выполнения», во время компиляции известно, что вызываемая функция - это та, на которую указывает n-й указатель в vtable. «Выяснение» подразумевает, что есть проверки типа и тому подобное, что не так.Once the run-time system figured out it would need to call a templatized virtual function
- является ли функция виртуальной, известно во время компиляции.void f(concr_base& cb, virt_base& vb) { cb.f(); vb.f(); }
, то он «знает», какая функция вызывается в вызываемой точкеcb.f()
, и не знает, для чегоvb.f()
. Последнее должно быть обнаружено во время выполнения , исполняющей системой . Если вы хотите назвать это «выяснением», и является ли это более или менее эффективным, это немного не меняет эти факты.Из шаблонов C ++ Полное руководство:
источник
C ++ не разрешает виртуальные функции-члены шаблона прямо сейчас. Наиболее вероятной причиной является сложность его реализации. Раджендра приводит веские причины, почему это нельзя сделать прямо сейчас, но это может быть возможно при разумных изменениях стандарта. Особенно трудно определить, сколько экземпляров шаблонной функции действительно существует, и создание виртуальной таблицы кажется трудным, если учесть место вызова виртуальной функции. У людей, занимающихся стандартизацией, сейчас есть много других дел, и C ++ 1x - большая работа и для авторов компиляторов.
Когда вам понадобится шаблонная функция-член? Однажды я столкнулся с такой ситуацией, когда я пытался реорганизовать иерархию с чисто виртуальным базовым классом. Это был плохой стиль для реализации различных стратегий. Я хотел изменить аргумент одной из виртуальных функций на числовой тип и вместо перегрузки функции-члена и переопределить каждую перегрузку во всех подклассах, я пытался использовать функции виртуального шаблона (и должен был выяснить, их не существует). .)
источник
Таблицы виртуальных функций
Давайте начнем с некоторой предыстории виртуальных таблиц функций и того, как они работают ( источник ):
Моя проблема, или как я сюда попал
Сейчас я пытаюсь использовать что-то подобное для базового класса cubefile с шаблонными оптимизированными функциями загрузки, которые будут реализованы по-разному для разных типов кубов (некоторые сохраняются по пикселям, некоторые по изображениям и т. Д.).
Некоторый код:
То, что я хотел бы, но это не скомпилируется из-за виртуальной шаблонной комбинации:
В итоге я переместил объявление шаблона на уровень класса. Это решение заставило бы программы знать о конкретных типах данных, которые они будут читать, прежде чем они их прочитают, что недопустимо.Решение
предупреждение, это не очень красиво, но это позволило мне удалить повторяющийся код выполнения
1) в базовом классе
2) и в детских классах
Обратите внимание, что LoadAnyCube не объявлен в базовом классе.
Вот еще один ответ переполнения стека с обходным путем : нужен обходной путь члена виртуального шаблона .
источник
Следующий код можно скомпилировать и запустить правильно, используя MinGW G ++ 3.4.5 в Windows 7:
и вывод:
И позже я добавил новый класс X:
Когда я попытался использовать класс X в main () следующим образом:
g ++ сообщает о следующей ошибке:
Итак, очевидно, что:
источник
Нет, они не могут. Но:
имеет тот же эффект, если все, что вы хотите сделать, это иметь общий интерфейс и отложить реализацию до подклассов.
источник
Foo
указатель квалифицирован какFoo<Bar>
, он не может указывать наFoo<Barf>
илиFoo<XXX>
.Нет, функции-члены шаблона не могут быть виртуальными.
источник
В других ответах предложенная функция шаблона представляет собой фасад и не дает никакой практической выгоды.
Язык не допускает функции виртуальных шаблонов, но с обходным путем можно иметь и то и другое, например, одну реализацию шаблона для каждого класса и виртуальный общий интерфейс.
Однако для каждой комбинации типов шаблонов необходимо определить фиктивную функцию виртуальной оболочки:
Вывод:
Попробуй здесь
источник
Чтобы ответить на вторую часть вопроса:
Это не необоснованная вещь, чтобы хотеть сделать. Например, Java (где каждый метод является виртуальным) не имеет проблем с общими методами.
Одним из примеров использования C ++ шаблона виртуальной функции в C ++ является функция-член, которая принимает универсальный итератор. Или функция-член, которая принимает объект универсальной функции.
Решением этой проблемы является использование стирания типов с boost :: any_range и boost :: function, что позволит вам принять универсальный итератор или функтор без необходимости превращать вашу функцию в шаблон.
источник
Существует обходной путь для «метода виртуального шаблона», если набор типов для метода шаблона известен заранее.
Чтобы показать идею, в приведенном ниже примере используются только два типа (
int
иdouble
).Там «виртуальный» метод шаблона (
Base::Method
) вызывает соответствующий виртуальный метод (один изBase::VMethod
), который, в свою очередь, вызывает реализацию метода шаблона (Impl::TMethod
).Нужно только реализовать метод шаблона
TMethod
в производных реализациях (AImpl
,BImpl
) и использоватьDerived<*Impl>
.Вывод:
NB:
Base::Method
на самом деле излишки для реального кода (VMethod
могут быть обнародованы и использованы напрямую). Я добавил его так, чтобы он выглядел как настоящий «виртуальный» метод шаблона.источник
Base
класс каждый раз, когда вам нужно вызвать функцию шаблона с типом аргумента, несовместимым с теми, которые были реализованы до сих пор. Избежание этой необходимости - это намерение шаблонов ...В то время как на старый вопрос, на который многие отвечали, я полагаю, лаконичный метод, не сильно отличающийся от других опубликованных, заключается в использовании второстепенного макроса для облегчения дублирования объявлений классов.
Итак, теперь, чтобы реализовать наш подкласс:
Преимущество здесь в том, что при добавлении нового поддерживаемого типа все это можно сделать из абстрактного заголовка и, возможно, отказаться от него в нескольких файлах исходного кода / заголовка.
источник
По крайней мере, в gcc 5.4 виртуальные функции могут быть членами шаблона, но должны быть самими шаблонами.
Выходы
источник
Попробуй это:
Напишите в classeder.h:
Проверьте, если вы работаете с этим, чтобы написать этот код в main.cpp:
источник