Эта проблема включает использование шаблонов для разрешения виртуальных элементов в шаблоне рассылки.
Примечание. Это не то же самое, что вопросы о методе виртуального шаблона, уже задаваемые в 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.
* Другие публикации связаны с использованием шаблонов для создания объявлений виртуальных методов. Я использую шаблоны для создания функций, которые реализуют абстрактные методы.
Так почему же компилятор генерирует, говоря, что класс
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 };
—конец примера ]
Кажется, ты действительно хочешь 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); }
};
Поскольку все типы полей имеют общий интерфейс, вы можете упростить проблему, изменив интерфейс, если это возможно:
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";
}
};