我可以在不使用include的情况下扩展头文件中的类吗
Can I extend a class in a header file without using include?
我有这三个文件:
头文件中定义的抽象类Person
:
Person.h
class Person {
public:
char * name;
virtual char * days_work(int count, int price) = 0;
};
扩展头文件中定义的Person
的类Miner
:
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
的顶部来编译它,但每个人都告诉我,将头文件包含在其他头文件中是不好的做法。在大多数情况下,我已经能够通过使用类的前向声明来避免它。(例如Miner.h
中的class Person;
),但在这种情况下不起作用。
我能在这个主题上找到的每个问题都建议包括头文件。我经常看到"快速而肮脏的解决方案"answers"狗和鸟的解决办法"之类的短语,但我找不到更好的了。
有没有一种方法可以在标头中定义类扩展,而不在标头中包含标头?
在这种情况下,你认为最佳做法是什么?
每个人都告诉我,在其他头文件中包含头文件是一种糟糕的做法
那么每个人都错了!头文件包括其他头文件绝对是正确和正常的做法。在这种情况下,这是必需的。
事实上,您不应该#包含您实际上并不需要的文件。有些人倾向于在不需要的情况下在其他标头中#包含大量标头(要么完全未使用,要么可能使用"前向声明"就足够了,例如,如果标头的唯一需要是声明指向其中声明的类的指针)。
所以,#包括你需要的,不要#包括你不需要的,"每个人"都应该快乐。
您问:
有没有一种方法可以在标头中定义类扩展,而不在标头中包含标头?
是的,但很痛苦。不要这么做。
任何时候使用
#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
基类的头文件。
如果扩展类Person
,则编译器必须知道该类的定义。
确实,您应该尽量将#include
的数量保持在最低限度(无论是否为头文件),因为每个新条目都可能增加要编译的代码量。在较大的项目中,您还可能遇到循环依赖关系的问题(文件A包括B,反之亦然)。在适用的情况下,应将include替换为转发声明。但有时,比如在您的情况下,包含是必要的。
是的一种糟糕做法,就是不使用#include
,并依赖于在您使用它们的所有.cpp
文件中,一个文件在另一个文件之前包含的事实。
包含头意味着您将在头文件(即include)中定义的代码插入到该文件的顶部。所以你必须小心,不应该有重复的定义。
在您的示例中,
#include"Person.h"at the top of Miner.h means
**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
所以有重复的人的定义,所以它应该给出错误。因此,当您将标头添加到另一个标头时,您必须非常小心
- 如何按文件扩展名引用文件夹中的文件
- 谁能告诉我,程序中的错误是什么?该程序仅用于获取文件扩展名
- 通过cMake使用具有自定义文件扩展名的共享库
- 在另一个字符串中插入文件扩展名之前的字符串
- 如何在不使用文件扩展名的情况下使用命令行参数打开C++中的文本文件?
- Eclipse CDT:传递具有相同文件扩展名的多个程序参数
- 将C 代码桥接到我的Swift代码中.哪些文件扩展名为XCode中的基于C的语言
- 如何打开并显示C 中任何文件扩展名的文件
- 循环浏览所有项目,其中QTREEVIEW QFILESYSTEMMODEL上具有所需的文件扩展名
- 如何调用 ShellExecute 以使用 C++ 打开具有特定程序的文件,而无需关联相同的文件扩展名
- 使用.rose(文件扩展)CPP的文件处理
- 用户定义的C 文件扩展名,用于G 汇编
- 如何在 INFLATE 后获取原始文件扩展名
- CMake:如何仅将特定文件扩展名从一个目录复制到另一个目录
- 获取文件扩展名
- C 中的自定义数据文件扩展
- 共享库的TX文件扩展名
- 如何创建一个不敏感的正则态度以匹配文件扩展名
- 如何更改QT上的文件扩展名
- 列出 OpenCV 支持的文件扩展名