C ++头文件只有项目 - 使用不同的程序集

时间:2013-02-20 09:27:02

标签: c++ visual-studio-2012 linker compiler-errors

我有一个项目,我必须将.cpp / header文件分开更改为将定义加入到头文件中。我尝试将cpp文件的内容最初复制到头文件中,但是我的ide - VS2012 express - 将我发送到一个循环,它表示头文件包含自己,所以当我删除include" class.h&#时34;它抱怨说,在Class :: functionname的情况下,无法识别Class。最终我决定在标题中定义定义,例如

class Thing {
public:
   void func { code; } 
}

这解决了我在项目上的编译问题。麻烦的是我有一个测试项目 - WinUnit - 我无法再访问这些功能。该项目曾经是一个静态库,并相应地链接,但因为没有.cpp文件,项目没有生成.lib。尝试更改为动态链接库,同样的问题 - 没有dll生成。所以我添加了一个项目引用,当我输入#include" Class.h"时,它似乎可以识别我的类文件。

我的问题是它仍然没有编译类。它根本无法识别测试项目的.cpp文件中的类名。我甚至尝试将头文件添加到测试项目中,仍然没有乐趣。我尝试将附加包含目录设置为指向标题所在的位置 - 没有用。

我该如何做到这一点?

编辑: 仍然卡住所以我创建了一个SSCCE,它工作正常,指向测试项目在Additonal INclude目录中的头文件目录,它工作。虽然主要项目编译得很好,但我注意到它有一个智能感知错误 - 标识符" ClassName"未定义。所有其他类都识别其他类。 #include" className"存在。当我构建测试项目时,第一个错误与此行有关的智能感知错误:错误1错误C2143:语法错误:缺少&#39 ;;'之前' *'

实际行是:ClassName * obj; - 它是一个私人变量。

测试项目中有629个错误 - 其他一些代码:c4430,c2061。我想这些只是与未被识别的类相关的初始问题的副作用......我迷失了,可以退出并重新思考失败了....

编辑:修复智能感知错误,以便所有错误现在都在Testproject中 - 最多可出现826个错误。包含它们时查看头文件但不识别任何类名。错误代码:c2061,c2065,c2923等

2 个答案:

答案 0 :(得分:1)

在您的示例代码中,func是私有的,因为这是类中的默认访问。也许你想要定义函数public,以便为你的测试代码和类的其他客户端访问。

如果您只是将函数定义放在标题中,您还必须使它们内联。显式(对于自由函数和完全专用的函数模板定义),或者隐式地,即在类定义中定义类方法。

你是对的,因为库不再产生任何编译输出,即你必须既不链接lib也不链接dll文件。因此,在使用该库的任何项目(包括您的测试项目)中,您不再需要指定要与该项目链接的库。毕竟,这是仅限标头库的原因之一:它们在编译时完全包含在内(而不是链接时间)。

如果您之前编译过的测试项目,它也应该在修改之后进行编译,前提是您之前已经测试了所有库类,并且没有对命名空间结构进行任何更改。

如果没有SSCCE以及从编译器中获得的正确错误,我们只能猜出您可能遇到的其他陷阱。

编辑:即使源头到头重构已正确完成,但有些事情会引起麻烦,这是循环包含。如果你有这些,你必须要么打破依赖关系,要么把两个类放在同一个头文件中,在两个类定义之后提供方法定义(记得明确地内联声明方法定义)

Edit2:循环包含的简单示例:类A和B都有一个方法可以调用另一个类的方法。因此,每个类方法的定义需要其他类方法的声明,即另一个类的前向声明是不够的。在正常情况下,源将包括两个标头并完成。在仅标题的情况下,编译器看起来像这样:

class A {
  B* b_;
public:
  A(B* b) : b_(b) {}
  void foo() {b_->meow();}
};

class B {
public:
  void bar() { A a(this); a.foo(); }
  void meow() { /* ... */}
};

编译器会抱怨B的使用和对B::meow()的调用。前者可以通过前方声明B来解决,后者不能。首先定义B无济于事,A和A::foo()会遇到同样的问题。因此解决方案必须如下所示:

class A {
  B* b_;
public:
  A(B* b) : b_(b) {}
  void foo();   //1
};

class B {
public:
  void bar() { A a(this); a.foo(); }
  void meow() { /* ... */}
};

inline void A::foo() {b_->meow();} //2

依赖于第二类的第一类'方法的定义要延迟到第二类定义之后。由于A需要B和B需要A,因此在仅头文件库中几乎没有意义将两个不同头中的这些混合类定义分开。

分离这些东西的方法是打破依赖关系。在上面的情况下可能看起来像这样:

class B_Interface
{
public: 
  virtual void meow() = 0;
};

class A {
  B_Interface* b_;
public:
  A(B_Interface* b) : b_(b) {}
  void foo() {b_->meow();} //OK this time
};

class B : public B_Interface {
public:
  void bar() { A a(this); a.foo(); }
  virtual void meow() { /* ... */}
};

这是以另外一个间接为代价的,但是将两个类的依赖关系分开,使得A等的测试更容易。

答案 1 :(得分:0)

我已经受够了,出于某种原因它仍然无法工作,这会浪费我的时间和精力。我回到了一个构造良好的项目,仅仅是标题的地狱。