[英]C++ header file only project - use from different assembly
我有一个项目必须更改,从将.cpp / header文件分离到将定义仅合并到头文件中。 我最初尝试将cpp文件的内容复制到头文件中,但是我的想法-VS2012 express-使我陷入一个循环,其中说头文件包含自身,因此当我删除include“ class.h”时,它抱怨说如果是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:语法错误:缺少';' 在“ *”之前
实际的行是:ClassName * obj; -这是一个私有变量。
测试项目中有629个错误-其他一些代码:c4430,c2061。 我想这些仅仅是与无法识别的班级相关的最初问题的副作用...迷路了,可能会退缩并重新思考失败的问题...。
编辑:修复了智能错误,现在所有错误都在Testproject中-上升到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() { /* ... */}
};
这是以另外一个间接为代价的,但是将两个类的依赖关系分开,使对A等的测试更加容易。
我受够了,由于某种原因它仍然无法工作,这已经浪费了我的时间和精力。 我回到了一个结构良好的项目,只剩下标题了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.