Как вы перегружаете шаблонную функцию (специализированную) в дочернем классе? - PullRequest
3 голосов
/ 12 августа 2011

У меня есть базовый класс с шаблонной функцией, который имеет общий шаблонный тип, а также специализированную версию.

#ifndef BASE_CLASS
#define BASE_CLASS

#include <iostream>

using namespace std;

struct Type1
{
};

struct Type2
{
};

class baseClass
{
    public:
    template<class Type>
    void doStuff(Type & t)
        {
        templateFunction(t);  
        }

    template<class Type>
    void templateFunction(Type & t);
};

template<class Type>
void baseClass::templateFunction(Type & t)
{
    cout << "This is the generic function!" << endl;
}

template<>
void baseClass::templateFunction(Type1 & t)
{
    cout << "This is the specialized function: - Type1" << endl;
}
#endif

У меня также есть дочерний класс, который наследуется от "baseClass". Однако дочерний класс требует другой функциональности для этой специализации.

#ifndef CHILD_CLASS
#define CHILD_CLASS

#include "BaseClass.h"

class ChildClass : public baseClass
{
    public:

};

template<>
void ChildClass::templateFunction(Type1 & t)
{
    cout << "We overloaded the specialized template function for type 1!" << endl;
}

#endif

Выше не компилируется:

ChildClass.h: 13: ошибка: нет функции-члена templateFunction, объявленной в ChildClassâ ChildClass.h: 13: ошибка: недопустимое объявление функции

Если я изменю «перегруженную» функцию на:

template<>
void baseClass::templateFunction(Type1 & t)
{
    cout << "We overloaded the specialized template function for type 1!" << endl;
}

Я получаю: ChildClass.h: 13: ошибка: переопределение пустого baseClass :: templateFunction (Type &) [with Type = Type1] BaseClass.h: 36: ошибка: исключить baseClass :: templateFunction (Type &) [with Type = Type1] - ранее объявлено здесь

Как правильно перегрузить специализированные шаблонные функции в дочерних классах?

Для справки, основной:

#include "BaseClass.h"
#include "ChildClass.h"

int main()
{
    Type1 first;
    Type2 second;

    baseClass theBaseClass;
    ChildClass theChildClass;


    theBaseClass.doStuff(first);
    theBaseClass.doStuff(second);

    theChildClass.doStuff(first);
    theChildClass.doStuff(second);

    return 0;
}

По предложению: Kerrek SB я изменил ChildClass на:

#ifndef CHILD_CLASS
#define CHILD_CLASS

#include "BaseClass.h"
class ChildClass : public baseClass
{
    public:
    template<class Type>
    void templateFunction(Type & t);
};

template<>
void ChildClass::templateFunction(Type1 & t)
{
    cout << "We overloaded the specialized template function for type 1!" << endl;
}

#endif

Выход:

This is the specialized function: - Type1
This is the generic function!
This is the specialized function: - Type1
This is the generic function!

Я надеялся на:

This is the specialized function: - Type1
This is the generic function!
We overloaded the specialized template function for type 1!
This is the generic function!

Так что это все еще не работает.

Ответы [ 2 ]

5 голосов
/ 11 января 2012

Причина, по которой она все еще не работает так, как вы хотели, заключается в том, что функция не является виртуальной в родительском классе.Однако невозможно иметь функцию виртуального шаблона.

Я вижу две основные опции:

  • , как предложил rhalbersma, создайте сам шаблон класса и затем переопределите нужные методы.(который теперь НЕ является шаблоном) в дочернем классе.
  • для специализированного метода, просто напишите новый метод с другим именем, который делает все, что вам нужно.

НоЯ уверен, что кто-то придумает лучшую идею ... =)

2 голосов
/ 10 января 2012

Вы можете создать шаблонный класс с виртуальной функцией, подобной этой:

template<typename T>
class B
{
    virtual void f() { std::cout << "base template implementation \n"; }
};

template<>
class B<Type1>
{
    virtual void f() { std::cout << "base specialized implementation \n"; }
};

template<typename T>
class D: public B<T>
{
    virtual void f() { std::cout << "derived template implementation \n"; }
};

template<>
class D<Type1>: public B<Type1>
{
    virtual void f() { std::cout << "derived specialized implementation \n"; }
};

B<Type1> b1;
B<Type2> b2;
D<Type1> d1;
D<Type2> d2;

b1.f();
b2.f();
d1.f();
d2.f();

Теперь есть 2 независимых измерения настройки: либо шаблон T, либо динамический тип (B против D).Для каждого экземпляра шаблона виртуальные функции могут быть переопределены.

Более распространенным является то, чтобы B был обычным классом с чисто виртуальными функциями (т.е. интерфейсом), а D был классом шаблона, производным от B. Этопозволяет по-разному определять виртуальные функции B для каждого экземпляра шаблона D (с подходящим значением по умолчанию).

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