Функция-член шаблона базового класса скрыта в производном классе, хотя и в другом списке параметров

0

Мне это интересно. Предположим, что у меня есть:

class Base
{
public:

    template<typename T>
    void foo(T& varT)
    {
        //
    }

    template<typename T, typename U>
    void foo(T& varT, U& varU)
    {
        //
    }
};

class Child : public Base
{
public:
    template<typename T, typename U, typename Z>
    void foo(T& varT, U& varU, Z& varZ)
    {
        //
    }
};

Теперь, когда я пробую это:

Child c;

char cVar;
int iVar;
float fVar;

c.foo(cVar);
c.foo<int>(cVar);
c.template foo<int>(cVar);

Ни один из вызовов не работает. Они всегда затенены ошибкой "Нет соответствующей функции-члена для вызова". Может ли кто-нибудь указать мне способ решить это? Я прочитал в стандарте, что унаследованные функции теневого шаблона объектов, но стандарт явно сказал, что список параметров должен быть таким же, если они затенены.

Цените помощь.

  • 1
    «но в стандарте прямо сказано, что список параметров должен быть таким же, если они затенены». Неверно. Это необходимо для переопределения виртуальных функций .
Теги:
templates
inheritance

2 ответа

6
Лучший ответ

Скрытие базовых элементов всегда происходит, когда у вас есть имя в производном классе, которое присутствует в базовом классе. Основная причина заключается в том, что желательно защищать использование производного класса от изменений в базовом классе: при условии, что имена из баз не были скрыты, если добавлена новая перегрузка в базовом классе, рабочий захват с производным членом может быть захвачен чтобы скорее ссылаться на базовый класс без указания в производном классе, что что-то может произойти в базовом классе. Если вы хотите сделать доступными базовые элементы, вы можете использовать декларацию using:

class Child : public Base
{
public:
     using Base::foo; // declare that you want look up members from the base class

     template<typename T, typename U, typename Z>
     void foo(T& varT, U& varU, Z& varZ)
     {
         //
     }
};

В вашем коде у вас было три вызова:

  1. c.foo(cVar) работает с объявлением using.
  2. c.foo<int>(cVar) не работает даже с объявлением using потому что вы не можете привязать ссылку non- const к int к значению char lvalue. Использование c.foo<char>(cVar) будет работать.
  3. c.template foo<int>(cVar) страдает от одной и той же проблемы. Поскольку c явно не является зависимым именем, нет необходимости использовать template в этом контексте.

Без объявления using вы можете вызвать участника, явно указав вызов, например:

c.Base::foo(cVar);
  • 0
    Здорово! Спасибо за разъяснения. Работает как шарм. Я приму этот ответ, как только это позволит мне :)
  • 0
    @dyp: я перефразировал предложение (и добавил немного обоснования, почему имена скрыты).
Показать ещё 1 комментарий
0

Вам нужно это: http://en.cppreference.com/w/cpp/language/using_declaration

Добавить в определение Child:

using Base::foo;

Ещё вопросы

Сообщество Overcoder
Наверх
Меню