Шаблонный метод над не шаблонным методом в производном классе - PullRequest
3 голосов
/ 01 января 2011
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);

Ответы [ 4 ]

6 голосов
/ 01 января 2011

Две причины -

  1. В C ++ функция-член переопределяет функцию-член базового класса, только если функция базового класса помечена как виртуальная.В противном случае C ++ рассматривает эти две функции как независимые, которые по совпадению имеют одно и то же имя.Это отличается от Java, где функции автоматически переопределяют функции базового класса.

  2. В C ++ функции-члены шаблона не могут быть помечены как виртуальные.Отчасти это связано с реализацией наиболее часто используемых виртуальных функций - vtables - в сочетании с системой создания шаблонов C ++.C ++ обрабатывает все экземпляры одного и того же шаблона для аргументов разных типов как отдельные функции и генерирует эти экземпляры лениво.Это проблема для реализации vtable, поскольку vtable требует статического определения во время компиляции количества различных виртуальных функций в классе, а также упорядочения по ним.Поскольку шаблонная виртуальная функция будет означать неизвестное число и порядок виртуальных функций в классе, C ++ запрещает это.

1 голос
/ 01 января 2011

Если вы вызываете func для объекта / указателя / ссылки типа A, вызывается A::func, поскольку func не является виртуальным (и не может быть: это функция шаблона).

Вы действительно тестировали свой код?

0 голосов
/ 01 января 2011

Поскольку B :: func НЕ является перегрузкой A :: func и никогда не может быть, независимо от того, что вы делаете.Даже не пытайтесь объявить A :: func виртуальным, потому что вы не можете.Что бы вы ни пытались сделать, вы не можете.Статический и динамический полиморфизм просто не смешивается в C ++.

Если бы ваш указатель был на B *, а не на A *, вы ожидаете, что его версия будет вызываться.

0 голосов
/ 01 января 2011

A::func() не объявлено как virtual, поэтому компилятор не будет генерировать виртуальную таблицу и любой другой код, необходимый для вызова B::func() во время выполнения. Это не имеет ничего общего с шаблонами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...