Метод шаблона по методу неэлемента в производном классе
Вопрос
class A {
public:
template<typename T> void func(size_t n, T values[]) { ... }
};
class B : public A {
public:
void func(size_t n, uint32_t values[]) { ... }
};
Почему функционирует B::func()
нет получить приоритет над шаблоном функции A::func()
При вызове этого кода?
uint32_t values[5];
A* obj = new B();
obj->func(5, values);
Решение
Две причины-
В C ++ функция элемента переопределяет только функцию элемента базового класса, если функция базового класса помечена виртуальной. В противном случае C ++ рассматривает две независимые функции, которые по совпадению имеют одинаковое имя. Это контрастирует с Java, где функции атоматически переопределяют функции базового класса.
В C ++ функции членов шаблона не могут быть помечены виртуальными. Отчасти это связано с реализацией виртуальных функций, которые наиболее часто используются - vtables - в сочетании с системой экземпляров C ++ шаблонов. C ++ обрабатывает все экземпляры одного и того же шаблона по аргументам различных типов, как отдельные функции, и лениво генерирует эти экземпляры. Это проблема для реализации VTable, поскольку VTable требует статического определения времени компиляции количества различных виртуальных функций в классе, а также упорядочение на них. Поскольку виртуальная функция шаблона будет означать неизвестное число и упорядочение виртуальных функций в классе, C ++ не имеет отношения к этому.
Другие советы
Если вы позвоните func
на объекте/указателе/ссылке типа A
, A::func
называется, так как func
не является виртуальным (и это не может быть: это шаблонная функция).
Вы действительно проверяли свой код?
A::func()
не объявляется как virtual
, поэтому компилятор не будет генерировать виртуальную таблицу и любой другой код, необходимый для обозначения B::func()
во время выполнения. Это не имеет ничего общего с шаблонами.
Потому что b :: func не является перегрузкой :: func и никогда не может быть, независимо от того, что вы делаете. Даже не пытайтесь объявить :: func virtual, потому что вы не можете. Что бы вы ни пытались сделать, вы не можете. Статический и динамический полиморфизм просто не смешивается в C ++.
Если бы ваш указатель был на B*, вместо A*, вы ожидаете, что ее версия будет вызвана.