【问题标题】:How to solve compilation errors when two classes in different h files uses each other? [duplicate]不同h文件中的两个类相互使用时如何解决编译错误? [复制]
【发布时间】:2012-07-15 04:20:10
【问题描述】:

可能重复:
Avoiding Circular Dependencies of header files

任务.h:

#ifndef Tasks_h
#define Tasks_h

#include "Executors.h"

class Task
{
    Executor *current_executor;
};

#endif Tasks_h

Executor.h:

#ifndef Executors_h
#define Executors_h

#include "Tasks.h"

class Executor
{
    Task *current_task;
};

#endif Executors_h

main.cpp:

#include <conio.h>
#include <stdio.h>
#include "Tasks.h"
#include "Executors.h"

int main()
{
    Executor ex;

    return 0;
}

编译错误:

Error   1   error C2146: syntax error : missing ';' before identifier 'current_task'    c:\users\rain\documents\visual studio 2010\projects\text\text\executors.h   8
Error   2   error C4430: missing type specifier - int assumed. Note: C++ does not support default-int   c:\users\rain\documents\visual studio 2010\projects\text\text\executors.h   8
Error   3   error C4430: missing type specifier - int assumed. Note: C++ does not support default-int   c:\users\rain\documents\visual studio 2010\projects\text\text\executors.h   8

再次...在 C# 中我永远不会遇到这样的问题,但我会尽力支持 C++ 并使用它。
不想在一个头文件中编写所有类

【问题讨论】:

  • 代码没有意义。 Executor 对象包含 Task 对象,而 Executor 对象又包含 Executor 对象。所以它是对象的无限递归。
  • 就目前而言,您有两个包含彼此实例的类,这显然是不可能的。你需要使用引用或指针来做这种事情。
  • 我知道,这只是一个例子。可能会有指针。编辑使用指针的主要问题

标签: c++ class header


【解决方案1】:

你可以使用前向声明:

//#include "Executors.h"

class Executor;
class Task
{
    std::shared_ptr<Executor> current_executor;
};

另一种方法是使用pimpl idiom:

在 .h 文件中(没有执行程序头文件/转发声明)

class TaskImpl;
class Task
{
 public:
    Task();
    String getExecutorName();

 private:
    std::unique_ptr<TaskImpl> impl;
    friend TaskImpl;    
};

在.cpp中

#include "Executors.h"

class TaskImpl {
   public:
   Executor current_executor;
   String getExecutorName() { return current_executor.name; }
};

Task::Task() : impl(new TaskImpl()) {
}

String Task::getExecutorName() { return impl->getExecutorName(); }

【讨论】:

  • 你需要一个指针:smart one or Executor* current_executor;
【解决方案2】:

我打赌你不知道你实际上在做什么:你有一个任务,其中一部分是执行者,其中一部分是任务,其中......

它不是 C# 或 Java 中的引用。

要做你真正想做的事,结合前向声明使用指针/引用

【讨论】:

    【解决方案3】:

    这只是一个例子。可能有指针代替

    如果你可以切换到使用指针,你可以用前向声明替换标题包含:

    #ifndef Executors_h
    #define Executors_h
    
    class Task;
    
    class Executor
    {
        Task *current_task_ptr;
    };
    
    #endif Executors_h
    

    【讨论】:

    • 你能不能说一下如何对派生类使用前向声明?例如,如果 Task 在其标头中派生自 BaseTask,如何转发声明它?像这样:类任务:BaseTask;?还是我可以像以前一样离开?
    • @Kosmos 不幸的是,继承一个类需要知道被继承类的结构(就像在另一个类中包含一个类的实例一样),因此无法通过前向声明来解决基类。您需要保留#include "BaseTask.h"
    • 如果我想像这样调用静态函数前向声明的类,我发现它也不起作用:class TEST_CLASS;然后在代码中的某个地方: TEST_CLASS::RunStaticMethod();糟糕的是它说“使用未定义的类型 TEST_CLASS”
    • @Kosmos Forward 声明使您能够创建指向类的指针,但几乎没有其他功能(没有继承,没有函数调用等)。原因是指向类的指针都是创造平等。知道类是在某处定义的,这就是 C++ 编译器为指针分配空间所需的全部内容。继承,包括在类中作为成员,调用成员函数等需要额外的信息,这些信息在类定义的头文件中提供。
    猜你喜欢
    • 2022-01-12
    • 2019-04-05
    • 2021-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-31
    • 1970-01-01
    相关资源
    最近更新 更多