【问题标题】:"invalid use of incomplete type". Solving circular dependencies“不完整类型的无效使用”。解决循环依赖
【发布时间】:2017-08-23 19:14:46
【问题描述】:

我是 C++ 的新手,我一直在尝试与其他问题不同的建议,但我无法让我的代码正常工作。

我有一个类“PChar”和另一个类“Action”。一个 Action 有两个 PChar 成员,一个 PChar 方法(“act()”)必须能够创建一个 Action 对象。所以在尝试了不同的事情之后,我得到了这个代码:

“action.h”:

#ifndef ACTION_H
#define ACTION_H

class PChar;

class Action
{
    PChar *subject, *object;
public:
    Action();
    Action(PChar& p1, PChar& p2);
};


#endif

“action.cpp”:

#include "action.h"

Action::Action(){};

Action::Action(PChar& p1,PChar& p2)
{
    *subject=p1;
    *object=p2;
};

“字符.h”

#ifndef CHARACTER_H
#define CHARACTER_H

#include <string>

#include "action.h"

class PChar
{
public:
    std::string name;

    PChar();

    PChar(std::string input_name);

    void act(PChar& target, Action &action);
};
#endif    

“字符.cpp”

#include "character.h"

PChar::PChar(){}

PChar::PChar(std::string input_name)
{
    name=input_name;
}

void PChar::act(PChar& target, Action& action)
{
    action=Action(*this, target);
}

“main.cpp”

#include "action.h"
#include "character.h"

int main()
{
    PChar char1("Joe");
    PChar char2("Matt");
    Action handshake;
    char1.act(char2, handshake);
}

目标是创建一个对象“握手”,其中包含两个字符作为成员。编译时出现错误:

action.cpp:7:10: error: invalid use of incomplete type ‘class PChar’
  *subject=p1;
          ^
In file included from action.cpp:1:0:
action.h:4:7: note: forward declaration of ‘class PChar’
 class PChar;
       ^
action.cpp:8:9: error: invalid use of incomplete type ‘class PChar’
  *object=p2;
         ^
In file included from action.cpp:1:0:
action.h:4:7: note: forward declaration of ‘class PChar’
 class PChar;
       ^

这是一个更大项目的一部分,这就是文件结构如此的原因,我只是简化了代码以重现错误。我已经尝试过其他类似问题的解决方案,但它们似乎不起作用。欢迎任何帮助或提示。谢谢!

【问题讨论】:

  • 当你转发声明一个类时,你仍然需要在使用它之前包含提供它定义的标题。例如,您需要在“action.cpp”中包含“character.h”。
  • 这个例子有严重的错误。 *subject=p1; 不会做你想做的事。 subject 是一个未初始化的指针。取消引用是未定义的行为。至少,您需要分配一个新的PChar 作为您的论点的副本。

标签: c++ circular-dependency incomplete-type


【解决方案1】:

C++ 需要知道一个类型的细节才能进行编译和赋值操作。

解决方案是将"Character.h" 也包含在"Action.cpp" 中。

【讨论】:

    【解决方案2】:

    您可以转发声明类型以声明指针或引用。但是当您开始使用该类型(将其声明为值或分配给它或调用方法)时,必须对其进行定义。在action.cpp 中包含character.h 将解决编译错误。请注意,您的 ctor 中有 UB:

    Action::Action(PChar& p1,PChar& p2)
    {
        *subject=p1;
        *object=p2;
    }
    

    当您取消引用未初始化的指针时。你需要让它们指向某个地方,可能你的意思是分配动态内存。在这种情况下,std::unique_ptr 会更好,因为Rule of 3/5/0 会解决问题:

    class Action
    {
        std::unique_ptr<PChar> subject, object;
    public:
        ...
    };
    
    Action::Action(const PChar& p1, const PChar& p2) :
        subject( new PChar(p1) ), object( new PChar(p2) )
    {
    }
    

    当您不打算修改对象时,最好将其作为 const 引用传递。

    【讨论】:

    • 谢谢!包括你说的作品,我不知道为什么我没有想到这一点。我将不得不阅读更多关于指针的内容以了解那里的问题。
    猜你喜欢
    • 2018-12-17
    • 2011-12-01
    • 2018-08-24
    • 1970-01-01
    • 1970-01-01
    • 2017-04-27
    • 2010-11-29
    相关资源
    最近更新 更多