我最近花了一些时间在我的C ++模板中搜索拼写错误。 g ++没有抱怨错字,所以我想知道是否有一种工具可以在将来检查这类问题?
这是一个演示正确编译的简化示例。我希望有关struct dummy的定义没有被定义,但似乎模板类goo隐藏了这一点。
foo.h中:
struct smart {
int x, y, z;
};
template<typename T> class goo
{
void barf(T* ptr){}
};
template<typename T> class foo
{
public:
foo(){};
private:
goo<T> x;
};
class bar: public foo<struct dummy>
{
public:
void do_something(struct smart& thing){}
};
Foo.cpp中:
#include "foo.h"
int main()
{
bar a;
struct smart b;
a.do_something(b);
return b.x+b.y+b.z;
}
使用g ++ foo.cpp成功编译
答案 0 :(得分:3)
编译器,设置为最高警告级别,是检测任何C ++问题的最佳工具。
我给你的建议有两个方面:
1)将编译器警告级别设置为最高级别。这将抓住许多错误,低级别可能会保持沉默。
2)使用编码样式,当你做错事时更容易产生编译器错误。例如:
class bar: public foo<struct dummy>
{
public:
void do_something(struct smart& thing){}
};
老实说,我不知道这段代码是否合法。我强烈怀疑没有,但看起来您确实宣布了一种新类型struct dummy
。编译器接受它,所以我不确定它是否合法。
这样做会得到很好的服务:
class bar: public foo<dummy>
{
public:
void do_something(struct smart& thing){}
};
现在永远不能将其解析为新的类型声明,编译器将拒绝它。这会早点发现你的问题。
答案 1 :(得分:2)
如果您没有使用模板类型参数(在您的示例中就是这种情况),代码就可以了,即使该类型不存在,或者您正在调用成员函数中的类型上的函数调用。这是以C ++的名义,如果你不使用它,你就不付钱(例如没有创建新的函数)。
答案 2 :(得分:2)
这是因为你使用struct dummy
,如果没有这样的struct退出,编译器被告知自动生成一个前向声明结构。如果您只使用dummy
而不使用struct
,则不会这样做而且会抱怨。
答案 3 :(得分:0)
Attilla已经钉了这个;不需要dummy
的定义
所以它可以保持不完整的类型。这非常有用
C / C ++的特性,因为它有助于信息隐藏和使用
减少编译时间。
例如:
// Afwd.h
class A;
A * getA ();
void processA(A *);
void printA (A *);
// t.cc
#include "Afwd.h"
void bar ()
{
A * a = getA ();
processA (a);
printA (a);
}
此处,A
的客户端无需查看其实施细节。这也具有以下优点:客户端不需要包含A
为了在原始示例中针对dummy
生成错误,必须在此翻译单元中使用该定义。
首先,ptr
需要以需要完整类型的方式使用,例如通过取消引用:
template<typename T> class goo
{
public:
void barf(T* ptr){
*ptr;
}
};
这仍然不是问题,因为函数barf
未被调用,因此未实例化:
template<typename T> class foo
{
public:
foo(){
x.barf (0);
};
private:
goo<T> x;
};
此代码现在生成错误。 bar
的构造函数实例化并调用foo
的定义,该定义实例化并调用barf
。