Pau*_*eny 7 c++ templates functor
我有一个类Foo,用于一个小型独立项目.它在Foo.h中有一个类定义,在实现文件Foo.cpp中实现了类的成员函数.
第一个问题 - 类Foo的成员函数之一是模板方法Foo :: doSomething(),这个方法的实现应该与Foo.h中的函数声明一起出现是否正确?
Foo :: doSomething()将被实例化的模板参数是两种Functor类型之一 - 类CalcA和CalcB.
我是不是该:
一般规则:
如果在foo.cpp之外使用foo :: doSomething()(即,如果它是公共的或通常是受保护的),它必须放在标题中.
如果没有,输入cpp文件是完全可以的,甚至是一个好主意(因为它使杂乱的文件远离头文件).
因此,如果仿函数仅用于cpp文件,那么通常也会将模板函数放在那里.如果这种情况发生变化,以后总能重构一下.
首先,您必须了解模板机制.模板不会被编译,它们在使用时会被实例化,然后编译它们的实例化.因此编译器需要使用模板函数在每个模块中拥有完整的模板定义,以便根据您传递的参数首先实例化它们.
要解决您的问题,有三种解决方案,但您会发现它们都会导致相同的结果.您可以在类定义中的头文件中实现整个模板(我们使用.hxx而不是.h来后缀它们以确保它们包含模板定义):
// Foo.hxx
#ifndef __FOO_HXX__
#define __FOO_HXX__
class Foo {
public:
template <class T>
void bar(const T& t) {
t.doSomething();
}
};
#endif
Run Code Online (Sandbox Code Playgroud)
或者您可以从类中外部化定义,但仍然在头文件中:
// Foo.hxx
#ifndef __FOO_HXX__
#define __FOO_HXX__
class Foo {
public:
template <class T>
void bar(const T&);
};
template <class T>
void Foo::bar(const T& t) {
t.doSomething();
}
#endif
Run Code Online (Sandbox Code Playgroud)
最后,您可以在外部文件中实现模板方法体(出于同样的原因,前缀为.cxx).它将包含方法的主体,但不包括"Foo.hxx".相反,它是"Foo.hxx",它将在类定义后包含"Foo.cxx".这样,当编译器解析#include指令时,它会在同一模块中找到整个模板定义,允许它实例化它:
// Foo.hxx
#ifndef __FOO_HXX__
#define __FOO_HXX__
class Foo {
public:
template <class T>
void bar(const T&);
};
#include "Foo.cxx"
#endif
// Foo.cxx
template <class T>
void Foo::bar(const T& t) {
t.doSomething();
}
Run Code Online (Sandbox Code Playgroud)
在这三种实现模板的方式之间进行选择取决于可读性(和品味).
第二个和第三个在生成的代码方面是等价的,但我宁愿不使用cxx文件解决方案,因为当你忘记反转include时,它经常会导致愚蠢的错误.
此外,众所周知的C++库(如STL或Boost)仅在头文件中提出其代码,这是良好设计的标志.通过在标题内使用外部定义,您可以阐明类的定义.您还可以阻止编译器自动内联方法,根据Herb Sutter http://www.gotw.ca/gotw/033.htm,这有时会导致结果不佳
| 归档时间: |
|
| 查看次数: |
12742 次 |
| 最近记录: |