仅C++头文件项目 - 使用不同的程序集
我有一个项目,我不得不从具有.cpp /头文件分离到只将头文件加入定义。我试图最初将cpp文件的内容复制到头文件中,但是我的ide - VS2012 express - 发送给我一个循环,它表示头文件包含它自己,所以当我删除包含“class.h”时,它抱怨说在Class :: functionname的情况下,Class不能被识别。最后,我决定在标题定义的定义本身例如仅C++头文件项目 - 使用不同的程序集
class Thing {
public:
void func { code; }
}
这固定在我的项目编译的问题。麻烦的是我有一个测试项目 - WinUnit - 我无法再访问这些函数。该项目曾经是一个静态库,并相应链接,但因为没有.cpp文件,该项目没有生成.lib文件。试图改变到动态链接库,同样的问题 - 没有DLL生产。所以我添加了一个项目引用,它似乎起作用,因为它在我输入#include“Class.h”时识别了我的类文件。
我的问题是它仍然不编译类。它根本无法识别测试项目的.cpp文件中的类名。我甚至尝试将头文件添加到测试项目中,但仍然没有喜悦。我尝试设置其他包含目录来指向标头的位置 - 没有用。
我该如何做到这一点?
编辑: 仍然卡住了,所以我创建了一个SSCCE,它工作正常,将测试项目指向Additonal INclude目录中的头文件目录,它工作正常。虽然主要项目编译好,我注意到它有一个intellisense错误 - 标识符“ClassName”未定义。其他所有类都可以识别其他类。 #include“className”存在。当我构建测试项目时,第一个错误与此行与智能感知错误相关:错误1错误C2143:语法错误:缺少';'在'*'之前
实际的行是:ClassName * obj; - 这是一个私人变量。
测试项目中有629个错误 - 其他代码:c4430,c2061。我猜这些只是最初的问题相关的类没有被识别的副作用...我失去了,可能退缩,并重新考虑失败这....
编辑:修复intellisense错误,所以所有的错误都在测试项目现在 - 上升到826错误。在包含它们时查看头文件,但不能识别任何类名。错误代码:c2061,c2065,c2923等
在您的示例代码func
是私有的,因为这是一个类中的默认访问。也许你想定义公开的功能,使其可以用于你的测试代码和其他类的客户端。
如果您只是将函数定义放入头文件中,您还必须将它们内联。显式地(对于自由函数和完全专用的函数模板定义),或者隐式地,即在类定义内部定义类方法。
你是对的,该库不再产生任何编译的输出,即你不得不链接一个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() { /* ... */}
};
这是以一个更间接的成本,但分隔两班的依赖,使人们能够更容易等测试
对不起,关于示例代码,我忘了说他们是在“public:”修饰符下定义的。我试着明确地把公开课变成公开课。我会尝试一个SSCCE未能尽快解决任何建议。 – 2013-02-20 09:48:59
'公共类'是Java或C#或其他,而不是C++。我将编辑修改器到您的示例代码中。但是,除了你之外,没有人知道你的代码实际上是什么样的,所以*没人知道问题可能是什么。 – 2013-02-20 09:51:21
感谢Arne,我拿出了“公共类”的东西,但“public:”修饰符正确 – 2013-02-20 09:53:36
我有足够的,由于某种原因,它仍然无法正常工作,这是浪费我的时间和精力。我回到一个构建良好的项目,只有头文件。
为什么你想从一个精心打造的项目转移到只有头部的项目? – 2013-02-20 09:40:40
为了使用SDK,但现在我发现了一个备用解决方案,所以已经回滚了! – 2013-02-21 20:48:57