类在编译时相互干扰

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 我不知道,谢谢。我编辑了,也许他在标题的某处有非常量变量。

以上是关于类在编译时相互干扰的主要内容,如果未能解决你的问题,请参考以下文章

“aspNetDisabled”类在哪里定义,为啥 ASP.NET 会为它呈现干扰性的重复 CSS“类”属性?

Intellij 编译失败:“已定义为”

Java 面试——即时编译( JIT )

如何断言特定类在其布局中没有任何 vtbl 指针?

java代码封装与编译

为啥结构必须与模板类在同一个命名空间中才能编译?