此问题涉及使用模板解析Dispatch模式中的虚拟成员 注意:这与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
是抽象的呢?
注意:我在Windows Vista上使用Visual Studio 2008。
* 其他帖子涉及使用模板创建虚拟方法声明。我使用模板创建实现抽象方法的函数。
答案 0 :(得分:2)
那么为什么编译器生成说类
Visitor_Name_Query_1
是抽象的呢?
因为标准是这样说的。 §14.5.2[temp.mem] / p4:
成员函数模板的特化不会覆盖a 基类的虚函数。 [示例:
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 };
- 结束示例]
答案 1 :(得分:0)
您似乎确实希望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); }
};
答案 2 :(得分: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";
}
};