难以构建多个文件解决方案

时间:2014-03-26 17:27:22

标签: c++ building

我正在尝试构建一个包含三个文件的解决方案。使用main.cpp,它是四个文件。

Entity.h

#pragma once

#include "SystemBase.h"

namespace Engine {

class Entity {
public:
    Entity() { }

    void s(SystemBase* sb) { }
};
}

SubscribersList.h

#pragma once

#include "SystemBase.h"
#include "Entity.h"

namespace Engine {

class SubscribersList {
    friend SystemBase;

public:
    SubscribersList() { }

    void f(Entity* e) { }
};
}

SystemBase.h

 #pragma once

 #include "SubscribersList.h"
 #include "Entity.h"

 namespace Engine {

class SystemBase {
public:
    SystemBase() { }

    void g(Entity* e) { }

private:
    SubscribersList m;

};
}

不要专注于标题中的方法主体。这只是为了让事情变得简单。我发现了两种构建解决方案的方法。 1.在所有类名之前写下单词class。但是当我试图将实现与原型分开时,它会崩溃。 2.将所有代码写入一个文件。 我不会/不会在所有类名之前编写关键字class来构建解决方案,当然我不会/不会在一个文件中编写一个大项目。那我为什么不能建造呢?什么是魔术?!

1 个答案:

答案 0 :(得分:0)

要理解循环头依赖的问题,我们首先需要理解类声明和定义之间的区别以及不完整类型的概念。

类型Type的原型或前向声明写为:

class Type;

这样的前向声明允许您创建指针并引用该类型。 但是,在声明其完整类型之前,您无法实例化,取消引用指针或使用对Type的引用。

Type的声明可以写成:

class AnotherType;

class Type {
public:
    void aMemberFunc();
private:
    AnotherType *m_theOtherThing;
};

现在我们可以创建声明实例,并且可以取消引用指向Type的指针。

然而,在m_theOtherThing取消引用或实例化之前AnotherType必须完全声明。

class AnotherType {
    Type m_aType;
}

应该这样做,这给了我们AnotherType的完整声明和定义。

这允许继续编写Type::aMemberFunc

的定义
void Type::aMemberFunc() {
    m_theOtherThing = new AnotherType();
}

如果不是按照这个顺序将此代码呈现给编译器,而是在前面提供TypeAnotherType的完整声明:

class Type {
public:
    void aMemberFunc();
private:
    AnotherType *m_theOtherThing;
};

class AnotherType {
    Type m_aType;
}

然后AnotherType *m_theOtherThing;将无法编译,因为AnotherType尚未在该点声明或转发。

切换顺序给出:

class AnotherType {
    Type m_aType;
}

class Type {
public:
    void aMemberFunc();
private:
    AnotherType *m_theOtherThing;
};

现在Type m_aType;将无法编译,因为Type尚未声明。在这种情况下,前瞻性声明不会做。

使用#pragma once而不是标题保护不会改变问题。 #pragma once仅确保标题包含一次,否则它不会影响编译器处理代码的顺序。它肯定不允许编译器在到达它们时忽略未定义的类型。

对于这种类结构,编译器无法在不使用前向声明的情况下处理它。