我有这三个文件:
头文件中定义的抽象类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
),但在这种情况下不起作用。
我可以在该主题上找到的每个问题都建议包含头文件。我一直看到“快速和肮脏的修复”和“狗和鸟的解决方案”之类的短语,但我找不到更好的东西。
有没有办法在标题中定义类扩展而不在标题中包含标题?
在这种情况下,您认为最佳做法是什么?
答案 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有重复的定义,所以它应该给出错误。因此,当您将标题添加到另一个标题
时,您必须非常小心