Reputation: 707
I have these three files:
Abstract class Person
defined in a header file:
Person.h
class Person {
public:
char * name;
virtual char * days_work(int count, int price) = 0;
};
Class Miner
which extends Person
defined in a header file:
Miner.h
class Miner: public Person {
public:
int gold_mined;
void days_work();
};
And the definition of the member functions of Miner
in a code file:
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;
}
When I compile this (with gcc) I get an invalid use of incomplete type ‘struct Person’
error. I can get it to compile by putting #include "Person.h"
at the top of Miner.h
, but everyone keeps telling me that including header files within other header files is bad practice. For the most part I have been able to avoid it by using forward declarations of classes. (e.g. class Person;
in Miner.h
), but that doesn't work in this case.
Every question I can find on the topic suggests including the header file. I keep seeing phrases like 'quick and dirty fix' and 'dog and bird solution', but I can't find anything better.
Is there a way to define a class extension in a header without including a header within a header?
What do you consider best practice in a situation like this?
Upvotes: 2
Views: 2536
Reputation: 2993
Including header means you are inserting the code defined in header file(which is include) at top of that file. So you have to be careful there should not be repeated definition.
In your example,
#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
So there is duplicate definition of Person, So it should give error. So you have to be very careful when you are adding header into another header
Upvotes: -1
Reputation: 21778
If you extend a class Person
, the definition of that class has to be known by the compiler.
It is true that you should try to keep the number of #include
s to minimum (header file or not), because every new entry potentially increases the amount of code to compile. In bigger projects you can also hit the problem of circular dependencies (file A includes B, and vice versa). Where appriopriate, includes should be replaced by forward declarations.
But sometimes - such as in your case - an include is necessary.
What is a bad practice, is to leave an #include
out and rely on the fact that one file is included before another in all .cpp
files you use them in.
Upvotes: 0
Reputation: 206627
You asked:
Is there a way to define a class extension in a header without including a header within a header?
Yes but painful. Don't do it.
Any time you use
#include "Miner.h"
you also have to add
#include "Person.h"
before that statement.
If you think about what #include
means -- the pre-processor includes the contents of the file in the compilation unit -- it will become clear.
Replace the line
#include "Miner.h"
with
class Miner: public Person {
public:
int gold_mined;
void days_work();
};
This is not valid code since the definition of the class Person
must be known before the above code can be compiled.
Now, replace the lines
#include "Person.h"
#include "Miner.h"
with
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();
};
Now, everything should compile just fine.
You also asked:
What do you consider best practice in a situation like this?
When defining a derived class, always #include
the header file of the base class.
Upvotes: 3
Reputation: 249273
Everyone keeps telling me that including header files within other header files is bad practice
Then everyone is wrong! Header files including other header files is absolutely the correct and normal thing to do. And it is required in this case.
What is true is that you should not #include files which you do not actually need. Some people tend to #include lots of headers in other headers when they are not required (either totally unused or perhaps a "forward declaration" would have sufficed, e.g. if the only need for the header is to declare a pointer to a class declared within it).
So, #include what you need, don't #include what you don't need, and "everyone" should be happy.
Upvotes: 7