【问题标题】: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 中定义

我快疯了。我不知道为什么会这样,也不知道如何解决。如果有人可以帮助我,我将非常感激,并且请,任何额外的建议都会很棒,因为我真的想尽可能多地学习这个项目。谢谢!

【问题讨论】:

    标签: c++ class namespaces


    【解决方案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 我不知道,谢谢。我编辑了,也许他在标题的某处有非常量变量。
        猜你喜欢
        • 2021-04-08
        • 2013-05-27
        • 1970-01-01
        • 2013-04-27
        • 1970-01-01
        • 2023-01-31
        • 2013-05-09
        • 2011-07-14
        • 1970-01-01
        相关资源
        最近更新 更多