我可以在不使用include的情况下扩展头文件中的类吗?

时间:2014-10-06 05:45:55

标签: c++ class polymorphism

我有这三个文件:

头文件中定义的抽象类Person

Person.h

class Person {
    public:
    char * name;
    virtual char * days_work(int count, int price) = 0;
};

Miner,它扩展了头文件中定义的Person

Miner.h

class Miner: public Person {
    public:
    int gold_mined;
    void days_work();
};

代码文件中Miner的成员函数的定义:

Miner.cpp

#include "Miner.h"
#include "Person.h"

Miner::Miner(char * name) {
    this->name = name;
    this->gold_mined = 0;
}
Miner::~Miner() {}
void Miner::days_work() {
    this->gold_mined += 10;
}

当我编译它(使用gcc)时,我收到invalid use of incomplete type ‘struct Person’错误。我可以通过将#include "Person.h"放在Miner.h的顶部来编译它,但是每个人都告诉我在其他头文件中包含头文件是不好的做法。在大多数情况下,我已经能够通过使用类的前向声明来避免它。 (例如class Person;中的Miner.h),但在这种情况下不起作用。

我可以在该主题上找到的每个问题都建议包含头文件。我一直看到“快速和肮脏的修复”和“狗和鸟的解决方案”之类的短语,但我找不到更好的东西。

有没有办法在标题中定义类扩展而不在标题中包含标题?

在这种情况下,您认为最佳做法是什么?

4 个答案:

答案 0 :(得分:4)

  

每个人都在告诉我,在其他头文件中包含头文件是不好的做法

然后每个人都错了!包含其他头文件的头文件绝对是正确和正常的事情。在这种情况下它是必需的。

真实的是你不应该#include你实际上并不需要的文件。有些人倾向于在不需要时在其他标题中包含大量标题(完全未使用或者可能是"前向声明"将足够,例如,如果标题的唯一需要是声明指针到其中声明的类)。

所以,#包括你需要的东西,不要#包括你不需要的东西,以及#34;每个人"应该很开心。

答案 1 :(得分:1)

你问:

  

有没有办法在标题中定义类扩展而不在标题中包含标题?

是的,但很痛苦。不要这样做。

任何时候使用

 #include "Miner.h"

你还必须添加

 #include "Person.h"
在该声明之前

如果您考虑#include的含义 - 预处理器包含编译单元中文件的内容 - 它将变得清晰。

替换

 #include "Miner.h"

class Miner: public Person {
    public:
    int gold_mined;
    void days_work();
};

这不是有效代码,因为在编译上述代码之前必须知道类Person的定义。

现在,替换

 #include "Person.h"
 #include "Miner.h"

class Person {
    public:
    char * name;
    virtual char * days_work(int count, int price) = 0;
};

class Miner: public Person {
    public:
    int gold_mined;
    void days_work();
};

现在,一切都应该编译得很好。

您还问:

  

在这种情况下,您认为最佳做法是什么?

定义派生类时,总是 #include基类的头文件。

答案 2 :(得分:0)

如果扩展类Person,编译器必须知道该类的定义。

确实应该尝试将#include的数量保持为最小(头文件与否),因为每个新条目都可能增加要编译的代码量。在更大的项目中,您还可以解决循环依赖的问题(文件A包括B,反之亦然)。在适当的地方,包括应由前瞻性声明取代。 但有时 - 例如在你的情况下 - 包含是必要的。

是一种不好的做法,就是让#include离开并依赖于在您使用它们的所有.cpp文件中包含一个文件之前的事实。

答案 3 :(得分:-1)

包含标头意味着您将在头文件(包括)中定义的代码插入该文件的顶部。所以你必须要小心,不应该重复定义。

在您的示例中,

#include Miner.h顶部的“Person.h”表示

**Miner.h**

class Person {
    public:
    char * name;
    virtual char * days_work(int count, int price) = 0;
};

class Miner: public Person {
    public:
    int gold_mined;
    void days_work();
};

It is fine.

But you add both the header in Miner.cpp

Miner.cpp
/* minor.h  start
class Person {
    public:
    char * name;
    virtual char * days_work(int count, int price) = 0;
};

class Miner: public Person {
    public:
    int gold_mined;
    void days_work();
};
*/ minor.h end

/*Person.h start
class Person {
    public:
    char * name;
    virtual char * days_work(int count, int price) = 0;
};

/*Person.h end

所以Person有重复的定义,所以它应该给出错误。因此,当您将标题添加到另一个标题

时,您必须非常小心