我正在尝试在一个文件中创建一个类,并在许多文件中使用该类。我很困惑......我不想要一个混乱的代码,一个文件中有一半的类,另一个文件中有一半的类。
app_core.cpp :(这里我们有班级)
class s1
{
private:
int gx;
public:
int gx(int x,int y)
{
gx = x;
}
};
app1.cpp :(这里我们使用的是)
#include "app_core.cpp"
class s1;
int show()
{
s1 new_s;
cout << new_s.gx(8, 7);
}
app2.cpp :(这里我们使用的是)
#include "app_core.cpp"
class s1;
int show()
{
s1 new_s;
cout << new_s.gx(18, 17);
}
如何归档上述内容?
答案 0 :(得分:2)
在C ++中#include something时,包含的文件或多或少地“粘贴”在该指令的位置。
有一个名为翻译单元的概念,它表示一个代码单元,它可以在将来被其他单元引用(在链接时)。
您想要的是编写翻译单元并向其他翻译单元提供有关如何访问该数据的信息。这是头文件的目的。
.h文件(.h按照惯例,您可以随意调用它)是一组声明,如
文件s1class.h
class s1
{
private:
int gxd;
public:
int gx(int x,int y)
{
gxd = x;
return x;
}
};
和
app1.cpp:
#include"s1class.h"
//... use s1 class
app2.cpp:
#include"s1class.h"
//... use s1 class
请注意一件事:你应该从不违反One Definition Rule,你可以根据需要声明多次(只要它们是一致的声明),但是你不能定义不止一次符号(例如一个函数)。 (小注意:#pragma一旦指令和类似的东西可以帮助你避免多次重新声明符号,并在多个地方多次包含标题时让你的生活更轻松。)
所以在上面的代码中,“gx”函数被定义到你的头文件中..该函数应该在每个使用它的翻译单元中存在一次。
在该特定情况下,它用于为app1.cpp和app2.cpp创建翻译单元。它应该违反ODR,对吗?它不会因为类的成员函数是隐式内联,这意味着它被“缝合”到调用者的身体中,从而被整合到调用者身份的一部分。
另一种方法是在头文件中声明内容,并在相关的cpp文件中实现:
s1class.h
#pragma once
class s1
{
private:
int gxd;
public:
int gx(int x,int y);
};
s1class.cpp
#include "s1class.h"
int s1::gx(int x,int y)
{
gxd = x;
return x;
}
并按上述步骤操作:只包含头文件,以便在链接时使用它(解析符号时)。
答案 1 :(得分:1)
您可以使用标头。 app1.h:
class s1
{
private:
int gx;
public:
int gx(int x,int y)
{
gx = x;
}
};
app2.cpp:
#include"app1.h"
//...
文件app1.h也应该与您编译的文件一起使用 或者添加像
这样的地址#include "D:\app1.h"
//...
如果你的文件app1.h在D:drive
中答案 2 :(得分:0)
首先,包含cpp文件是非常错误的样式。理论上,您可以将app_core.cpp中的所有代码写入app_core.h等标头中。虽然这在大多数情况下都有效,但它可能导致不必要的长编译时间。
但是,如果你真的想这样做,你必须从两个.cpp文件中省略class s1;
。
如果标题和来源之间的分割是你所说的“凌乱的代码”,那么我很抱歉但是没有,没有通用的方法来实现它。
答案 3 :(得分:0)
构建头文件。
app1.h
class s1
{
private:
int gx;
public:
int gx(int x,int y)
};
app1.cpp
#include "app1.h"
int s1::gx(int x,int y)
{
gx = x;
}
app2.cpp
#include "app1.h"
// your code that calls s1 methods
答案 4 :(得分:0)
我认为这可以解决您的“问题”:将您的类放在标题中,并在标题中实现它(这称为例如库“仅标题”)。
#ifndef CLASS1_H
#define CLASS1_H
class s1
{
private:
int gx;
public:
int gx(int x,int y)
{
gx = x;
}
};
#endif //CLASS1_H
然后,每个需要的#include "Class1.h"
只需.cpp
。
在一个文件中有一个类(没有声明和实现的分离)。请注意,虽然有时候方便,但使用“仅限标题”的代码有其缺点:
现在,实现与声明相关联,这意味着对实现的任何更改都意味着您必须重新编译包含此标头的代码。
编译将花费更多时间,因为编译单元必须查看翻译单元中的每个实现,而不仅仅是接口。
与您的信念相反,拥有一个标题和一个实现文件并不是很混乱。它有其优点,是一种广泛使用的实践。但是,它的一个缺点是你必须管理两个文件。