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

Can I extend a class in a header file without using include?

本文关键字:文件 扩展 情况下 include 我可以      更新时间:2023-10-16

我有这三个文件:

头文件中定义的抽象类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

所以有重复的人的定义,所以它应该给出错误。因此,当您将标头添加到另一个标头时,您必须非常小心