类在编译时相互干扰
Posted
技术标签:
【中文标题】类在编译时相互干扰【英文标题】:Classes interfering with each other on compile 【发布时间】:2012-02-12 18:11:01 【问题描述】:我正在开发一个 C++ 项目。
我有一个类及其函数,然后我意识到其中一些函数与该类无关,而只是数学函数,因此我决定将它们移至命名空间。
我的第一个问题是,c++ 命名空间的适当文件扩展名是什么?
我有一个 constants.h 文件,我计划在其中保存全局常量,例如 PI。
现在:
#include <math.h>
const double PI = M_PI;
我有之前讲过的命名空间,现在叫做:specificMath.h
#include <stdlib.h>
#include "constants.h"
... more code
我有一个 gaussian.cpp:
#include "gaussian.h"
#include "specificMath.h"
#include <iostream>
... more code
这个文件包含一个现在什么都不做的 main 函数,我只是无法让整个项目在没有 main 的情况下编译...
我有一个 gaussian.h,其中没有包含任何内容,这有问题吗?
第三个类,它没有属性,只有方法(同样,这是错的吗?还是不漂亮?)。截断函数.cpp
#include "specificMath.h"
#include <stdlib.h>
#include "truncatedFunctions.h"
#include "gaussian.h"
using namespace specificMath;
还有它的 truncatedFunctions.h,我又一次没有包括任何东西。
还有我包括的第四节课
#include "margin.h" //Its header, where I'm not including anything
#include "gaussian.h"
#include "specificMath.h"
using namespace specificMath;
当我“制作”它时,它似乎编译得很好,但是当它到达链接部分时,我得到了很多错误,说我的 margin.cpp 类上的东西首先在 truncatedFunctions.cpp 中定义
我快疯了。我不知道为什么会这样,也不知道如何解决。如果有人可以帮助我,我将非常感激,并且请,任何额外的建议都会很棒,因为我真的想尽可能多地学习这个项目。谢谢!
【问题讨论】:
【参考方案1】:当我“制作”它时,它似乎编译得很好,但是当它到达链接部分时,我得到了很多错误,说我的 margin.cpp 类上的东西首先在 truncatedFunctions.cpp 中定义
您是否在您的 specificMath.h 中定义您的函数?你应该只声明那些函数。
例如,如果您的 specificMath.h 包含函数定义,例如
#ifndef COOL_STUFF_NSPC
#define COOL_STUFF_NSPC
#include <iostream>
namespace coolstuff
void print(void)std::cout << "I'm declared in a header file." << std::endl;
#endif
并且您正在使用在其他几个文件中包含此文件,链接器快疯了。 包括意味着复制。因此,您已经多次定义了自己的coolstuff::print
。更好的方法(也是在许多文件中使用自写函数时唯一可能的方法)是将代码拆分为头文件和实现,就像在 gaussian 中所做的那样。
// coolstuff.namepace.h
#ifndef COOL_STUFF_NSPC
#define COOL_STUFF_NSPC
namespace coolstuff
void print(void);
#endif
当你包含coolstuff.namespace.h 时,它只会声明函数。而且你可以多次声明同一个函数。
// coolstuff.namespace.cpp
#include <iostream>
#include "cs.h"
void coolstuff::print(void)
std::cout << "Hello world!" << std::endl;
.cpp 文件包含您的函数的实现。现在你的链接器不会生气了,因为coolstuff::print
只有一个实现,而不是 n(其中 n 是你使用的 #include "cs.namespace.h"
的数量)。
我的第一个问题是,c++ 命名空间的适当文件扩展名是什么?
没有标准的命名空间扩展。将 .h/.cpp 用于标头/实现和自定义前缀,例如“nmspc”或“nsc”。这取决于你。
【讨论】:
【参考方案2】:很难判断您是否在代码中做错了什么(因为您没有显示任何错误),但首先要尝试“清理”您的构建并重新构建全部 em> 你的代码。如果编译器(不知道您在使用什么)由于某种原因没有编译所有修改过的模块,那么链接器出现问题也就不足为奇了。
我的第一个问题是,c++ 命名空间的适当文件扩展名是什么?
在 C++ 中,头文件通常是 .h
或 .hpp
。这对编译器来说并不重要。
#include "gaussian.h" #include "specificMath.h" #include <iostream>
一般来说,#include
标准库中的东西是个好主意首先,然后是你自己的东西。
我有一个 gaussian.h,其中没有包含任何内容,这有错吗?
没有。如果您不需要包含任何内容,请不要包含任何内容。
【讨论】:
【参考方案3】:首先,对标头使用包含保护。
#ifndef MYHEADER_H
#define MYHEADER_H
//header contents
#endif
这将防止同一个标题在同一个翻译单元中被包含两次。
其次,不要在标题中定义 uncosnt 内容:
double x = 0;
这将导致所有翻译单元导出该符号。
在您的标头中声明变量extern
,并在实现文件中为其提供定义。
【讨论】:
C++头文件中const
标量声明没有错;没有必要为此使用笨拙的extern
。事实上,使用extern
可能会导致编译器错过优化,否则它可能会知道实际数据值。
@GregHewgill 我不知道,谢谢。我编辑了,也许他在标题的某处有非常量变量。以上是关于类在编译时相互干扰的主要内容,如果未能解决你的问题,请参考以下文章