【问题标题】:What is the relationship between multiple header files and classes?多个头文件和类之间有什么关系?
【发布时间】:2012-02-17 02:39:53
【问题描述】:

我在这里有一个菜鸟问题。 我对 C++ 结构和语法有所了解,但遇到了一些困难。 我知道我的概念中遗漏了一些东西。因此,首先编写一些代码来帮助描述情况。

控制.h

#pragma once
#ifndef CONTROL_H
#define CONTROL_H

class Control
{
    public:
        Control();
        ~Control();
    private:
    public:
};

#endif /*CONTROL_H*/

控制.cpp

#include "Control.h"
#include "Hello.h"

Hello helloObj;

Control::Control()
{
}

Control::~Control()
{
}

int main()
{
    int a = helloObj.HelloWorld();
    return 0;
}

你好.h

#pragma once
#ifndef HELLO_H
#define HELLO_H

class Hello
{
    public:
        Hello();
        ~Hello();
    private:
    public:
         int HelloWorld(void);
};
#endif /*HELLO_H*/

你好.cpp

#include "Hello.h"

Hello::Hello()
{
}

Hello::~Hello()
{
}

int HelloWorld()
{
    return 5;
}

我尝试在 OSX 10.7 上使用 g++ 编译 control.cpp 并得到

Undefined symbols for architecture x86_64:
      "Hello::Hello()", referenced from:
              __static_initialization_and_destruction_0(int, int)in cccZHWtd.o
      "Hello::~Hello()", referenced from:
              ___tcf_1 in cccZHWtd.o
      "Hello::HelloWorld()", referenced from:
              _main in cccZHWtd.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status

是编译器、我的代码还是我对正在发生的事情的概念? 我没有正确实例化某些东西吗?

任何更详细描述此内容的链接将不胜感激。

最终我希望能够在另一个类中运行一个函数并返回结果......正常的 OO,保持你的程序模块化的东西......

【问题讨论】:

  • Hello.cpp 中应该是int Hello::HelloWorld(),但除此之外——您确定Hello.cpp 包含在您的构建中吗?你传递给编译器的是什么?

标签: c++ class header modular


【解决方案1】:

您遇到的错误是链接错误而不是编译错误。
链接器无法找到所述函数的定义,因此它报告错误。您似乎没有在项目中包含包含函数定义的Hello.cpp 文件。

确保Hello.cpp 包含在您的项目中并且是您项目的一部分,或者
如果您使用命令行进行编译和链接,请确保您在命令行的文件名中指定了Hello.cpp

【讨论】:

    【解决方案2】:

    大部分问题是我不熟悉 g++(感谢 Als)。 语法问题也很少(感谢 Brain)。

    这里是更正后的代码和 g++ 命令

    控制.h

    #pragma once
    #ifndef CONTROL_H
    #define CONTROL_H
    
    class CONTROL
    {
        private:
           //nothing defined yet...
        public:
            Control(); //default constructor
            ~Control(); //default destructor
    };
    #endif /*CONTROL_H*/
    

    控制.cpp

    #include "Hello.h"
    #include "Control.h"
    
    Hello helloTest; //instantiates the Hello Object
    
    Control::Control()
    {
    }
    
    Control::~Control()
    {
    }
    
    int main()
    {
        helloTest.HelloWorld();
        return 0;
    }
    

    你好.h

    #pragma once
    #ifndef HELLO_H
    #define HELLO_H
    
    class Hello
    {
        private:
            //nothing defined yet
        public:
            Hello(); //default constructor
            ~Hello(); //default destructor
    
            void HelloWorld();
    };
    #endif /*HELLO_H*/
    

    你好.cpp

    #include "Hello.h"
    #include <iostream> //so we can use 'cout'
    
    using namespace std;
    
    Hello::Hello()
    {
    }
    
    Hello::~Hello()
    {
    }
    
    void Hello::HelloWorld()
    {
        std::cout << "Hello lovelies!\n"; //The magic word.
    }
    

    然后我们像这样运行 g++

    g++ -o 你好./Control.cpp ./Hello.cpp

    g++ [选项] [输出文件名] [输入文件]

    【讨论】:

      【解决方案3】:

      首先:

          public:
          Hello();
          ~Hello();
          private:
          public:
      

      没有意义,一个类默认是private的,没必要弄 公开两次,我也不知道你是否可以这样做,如果你没有私人成员私人不应该在那里(不是试图意味着一些建议:-))

      现在回答这个问题(猜测免责声明:我不是 100% 熟悉 GCC):

      这是一个链接器错误,可能是因为 编译器找不到定义 你好世界(无效);。 让我解释一下:

      在你写的头文件中:

      int HelloWorld(void);
      

      但是在你的 .cpp 中你写:

      int HelloWorld()
      {
         return 5;
      }
      

      函数的(或者在这种情况下是方法,因为它在一个类中) 标头和源中的参数必须完全相同,您 甚至不能更改名称(或者至少你不能使用 VC++,它是 我用什么;我对 gcc 的经验很少)所以这可能是可以解决的 通过输入

      int HelloWorld(void)
      {
         return 5;
      }
      

      下一个(免责声明我不是 100% 熟悉 pre-proccsor):

      您还使用#pragma once pre-proccsor 标签,我不使用它,但 我相信这意味着您只能包含一次文件,并且您已包含 Hello.h 和 Control.h 两次,就像我说我不是预处理器专家但您注释掉了

      HELLO_H

      CONTROL_H

      【讨论】:

      • 是的,你可以在你的课堂上尽可能多地使用“public:”;在 C++ 中(与 C 不同),没有参数的函数签名与明确表示“void”的函数签名相同;而#pragma once 意味着如果一个文件在同一个翻译单元中包含多次(顺便说一句,在这个例子中没有发生),它只会被处理一次,这样做不是错误。
      • @DanHulme 是的,说 () 和 (void) 做同样的事情是一样的,但是我建议链接器可能认为它们是两个完全不同的事情,因为它们不一样,这就是它在 VC++ 中的方式。
      猜你喜欢
      • 2016-11-05
      • 1970-01-01
      • 1970-01-01
      • 2016-10-11
      • 2015-09-21
      • 2013-03-07
      • 2013-10-30
      • 2015-01-02
      • 2012-07-03
      相关资源
      最近更新 更多