1

我最近花了一些时间在我的 C++ 模板中寻找一个错字。g++ 没有抱怨错字,所以我想知道将来是否有可以检查此类问题的工具?

这是一个演示正确编译的简化示例。我希望有人抱怨没有定义 struct dummy,但似乎模板化的类 goo 隐藏了这一点。

富.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 成功编译

4

4 回答 4

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){}
};

现在这永远不能被解析为新的类型声明,编译器将拒绝它。这会及早发现您的问题。

于 2012-05-15T18:06:17.303 回答
2

如果您没有使用模板类型参数(在您的示例中就是这种情况),则代码是可以的,即使该类型不存在或者您正在调用未调用的成员函数中的类型的函数。这是以 C++ 的名义,如果你不使用它,你就不用为它付费(例如,没有创建新函数)。

于 2012-05-15T18:02:55.197 回答
2

这是因为您使用struct dummy编译器被告知如果没有这样的结构退出,则自动生成前向声明结构。如果你dummy不使用struct它就不会这样做,它会抱怨。

于 2012-05-15T18:12:14.430 回答
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

于 2012-08-02T19:21:00.100 回答