Метод шаблона по методу неэлемента в производном классе

StackOverflow https://stackoverflow.com/questions/4575491

  •  14-10-2019
  •  | 
  •  

Вопрос

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);
Это было полезно?

Решение

Две причины-

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

  2. В 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*, вы ожидаете, что ее версия будет вызвана.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top