Использование шаблонов для разрешения виртуальных методов

Эта проблема включает использование шаблонов для разрешения виртуальных элементов в шаблоне рассылки.
Примечание. Это не то же самое, что вопросы о методе виртуального шаблона, уже задаваемые в StackOverflow.. *

Правка 1: исправлены синтаксические ошибки, добавлены пояснения.

Учитывая следующее:

#include <string>
#include <iostream>

class Field_Interface
{
public:
virtual std::string  get_field_name(void) const = 0;
};

class Field_Integer : public Field_Interface
{
public:
std::string get_field_name(void) const
{ return "INT";}
};

class Field_String : public Field_Interface
{
public:
std::string get_field_name(void) const
{ return "VARCHAR";}
};

class Field_Double : public Field_Interface
{
public:
std::string get_field_name(void) const
{ return "DOUBLE";}
};class Abstract_Visitor
{
public:
virtual void visit(const Field_Integer& fi) = 0;
virtual void visit(const Field_String& fi) = 0;
virtual void visit(const Field_Double& fi) = 0;
};

class Visitor_Name_Query_1 : public Abstract_Visitor
{
public:
template <class Field>
void visit(const Field& f)
{
std::cout << "Field name is: "<< f.get_field_name()
<< "\n";
}
};

class Visitor_Name_Query_2 : public Abstract_Visitor
{
public:
void visit(const Field_Integer& fi)
{ print_field_name(fi); }

void visit(const Field_String& fi)
{ print_field_name(fi); }

void visit(const Field_Double& fi)
{ print_field_name(fi); }

private:
void print_field_name(const Field_Interface& fi)
{
std::cout << "Field name is: "<< fi.get_field_name()
<< "\n";
}
};

int main(void)
{
Visitor_Name_Query_1    q1;
Field_Integer           fi;
q1.visit(f1);
return 0;
}

Компилятор говорит шаблонный метод в Visitor_Name_Query_1 не разрешает абстрактный интерфейс Abstract_Visitor,

Редактировать 2: Результаты g ++

# g++ -o main.exe main.cpp
main.cpp: In function `int main()':
main.cpp:75: error: cannot declare variable `q1' to be of type `Visitor_Name_Query_1'
main.cpp:75: error:   because the following virtual functions are abstract:
main.cpp:35: error:  virtual void Abstract_Visitor::visit(const Field_Integer&)
main.cpp:36: error:  virtual void Abstract_Visitor::visit(const Field_String&)
main.cpp:37: error:  virtual void Abstract_Visitor::visit(const Field_Double&)
main.cpp:77: error: `f1' undeclared (first use this function)
main.cpp:77: error: (Each undeclared identifier is reported only once for each function it appears in.)

Visitor_Name_Query_1 это попытка упростить класс Visitor_Name_Query_2, Когда число visit методов растет за пределы простого количества (например, 5), обслуживание становится утомительным. Это причина template декларация.

Когда шаблон раскрывается одним из типов полей, объявление совпадает с Visitor_Name_Query_2,

Так почему же компилятор говорит, что class Visitor_Name_Query_1 абстрактный?

Примечание. Я использую Visual Studio 2008 в Windows Vista.

* Другие публикации связаны с использованием шаблонов для создания объявлений виртуальных методов. Я использую шаблоны для создания функций, которые реализуют абстрактные методы.

-2

Решение

Так почему же компилятор генерирует, говоря, что класс Visitor_Name_Query_1 абстрактный?

Потому что стандарт так говорит. §14.5.2 [temp.mem] / p4:

Специализация шаблона функции-члена не отменяет
виртуальная функция из базового класса. [ пример:

class B {
virtual void f(int);
};
class D : public B {
template <class T> void f(T); // does not override B::f(int)
void f(int i) { f<>(i); }     // overriding function that calls
// the template instantiation
};

конец примера ]

2

Другие решения

Кажется, ты действительно хочешь Abstract_Visitor иметь реализацию по умолчанию. Если вы переместите template в Abstract_Visitor, вы можете позволить каждому virtual посетитель имеет реализацию по умолчанию.

class Abstract_Visitor
{
template <class Field>
void visit(const Field& f)
{
std::cout << "Field name is: "<< f.get_field_name()
<< "\n";
}
public:
virtual void visit(const Field_Integer& fi) { visit<>(fi); }
virtual void visit(const Field_String& fi) { visit<>(fi); }
virtual void visit(const Field_Double& fi) { visit<>(fi); }
};
0

Поскольку все типы полей имеют общий интерфейс, вы можете упростить проблему, изменив интерфейс, если это возможно:

class Abstract_Visitor
{
public:
virtual void visit(const Field_Interface& f) = 0;
};

class Visitor_Name_Query_3 : public Abstract_Visitor
{
public:
void visit(const Field_Interface& f)
{
std::cout << "Field name is: "<< f.get_field_name()
<< "\n";
}
};
0
По вопросам рекламы [email protected]