So far I've looked up most of the typical solutions for cases of this error and yet non of them seems to work with my code. I'm using dev-c++
The structure of problematic class is following.
m.hh
#ifndef M_H
#define M_H
#include "z.hh"
#include <iostream>
#include <string>
using namespace std;
class M: public Z
{ /* this line is marked by the compiler as errorneous */
void m1();
void m2();
};
#endif
m.cpp
#include <iostream>
#include <string>
#include "m.hh"
using namespace std;
void M::m1() {/*bla bla*/};
void M::m2() {/*bla bla*/};
}
EDIT:
z.hh
#ifndef Z_H
#define Z_H
#include "m.hh"
#include <iostream>
#include <string>
using namespace std;
class Z;
static Z* s(string g, string i);
#endif
z.cpp
#include "z.hh"
#include <iostream>
#include <string>
class Z
{
public:
string i;
string g;
void set_i(string im) {i = im;}
string get_i() {return i;}
string get_g() {return g;}
virtual void m1()=0;
virtual void m2()=0;
Z* s(string g, string i) {
Z * z;
if(g=="m"){
M * z = new M;
}
}
};
Thanks!
Remove #include "m.hh" from z.hh to fix the circular include.
THE PROBLEM
You cannot derive from an incomplete type, which is what Z is in m.hh.
Upon deriving from a type the compiler must know the definition of said type. Just imagine you are trying to call a derived member function from Z on an object of type M, how would the compiler know if such call is a valid construct without knowing if Z actually declares such member?
And, a more relevant point, how would M be able to initialize Z without knowing what Z is?
THE SOLUTION
Move the definition of class Z to z.hh, and leave the definitions of its member functions in z.cpp (the same way you have split up M across m.hh, and m.cpp).
Well, the z.cpp file is actually a class declaration and should be a header file. A forward decalaration is only sufficient when you deal with pointers to that class, but not for inheriting from one (the compiler does need to know z's class layout for that).
The z.hh is not really needed, and the function declaration in it is not what you think (it's not a member function declaration). You can delete it and rename z.cpp to z.hh.
Ok, the exchange with #Luchian Grigore made me realize what you probably wanted and why you had "two z.hh". Z is to produce an M, but M inherits from Z, so there is a circular dependency. In C/C++ the way to break such a circle is to limit what one of the classes needs to know from the other: In order to declare a member function s that produces a pointer to a new M Z's class declaration only needs a typename M, not a the whole class declaration. So just a forward declaration (class M;) that introduces the type name M into the declaration of Z is enough; if the pointer to the M object is returned as a pointer to the base, Z, M's name is not even needed at all when Z is declared.
The definition of the factory function (be it file static or a member function) needs, if it is to produce an M, M's complete declaration though. That would be in a seaparate cpp file, which would include a complete header with M's full declaration.
Related
Is there a way to avoid the Graph:: repetition in the implementation file, yet still split the class into header + implementation? Such as in:
Header File:
#ifndef Graph_H
#define Graph_H
class Graph {
public:
Graph(int n);
void printGraph();
void addEdge();
void removeEdge();
};
#endif
Implementation File:
Graph::Graph(int n){}
void Graph::printGraph(){}
void Graph::addEdge(){}
void Graph::removeEdge(){}
I'm guessing this is to avoid lots of "unnecessary typing". Sadly there's no way to get rid of the scope (as many other answers have told you) however what I do personally is get the class defined with all my function prototypes in nice rows, then copy/paste into the implementation file then ctrl-c your ClassName:: on the clip board and run up the line with ctrl-v.
If you want to avoid typing the "Graph::" in front of the printGraph, addEdge etc., then the answer is "no", unfortunately. The "partial class" feature similar to C# is not accessible in C++ and the name of any class (like "Graph") is not a namespace, it's a scope.
No there's not. Not directly at least. You could go for preprocessor tricks, but don't do it.
#define IMPL Graph::
IMPL Graph(int n){}
void IMPL printGraph(){}
void IMPL addEdge(){}
void IMPL removeEdge(){}
Also, you shouldn't even want to do it. What's the point. Besides it being a C++ rule, it lets you know you're actually implementing a member function.
One option is using. If you have method definitions which are in a cpp file that never gets #included, then using is safe (doesn't affect other files):
foo.h:
class FooLongNameSpecialisationsParamaters
{
int x_;
public:
int Get () const;
void Set (int);
};
foo.cpp:
#include "foo.h"
using Foo = FooLongNameSpecialisationsParamaters;
int Foo::Get () const
{
return x_;
}
void Foo::Set (int x)
{
x_ = x;
}
main.cpp:
#include "foo.h"
int main ()
{
//Foo foo; <-- error
FooLongNameSpecialisationsParamaters foo;
return 0;
}
No, there is no way to avoid it. Otherwise, how would you know if a given function definition is for a class function or for a static function?
If you are asking if you can define a member function such as Graph::printGraph without specifying the class name qualification, then the answer is no, not the way that you want. This is not possible in C++:
implementation file:
void printEdge(){};
The above will compile just fine, but it won't do what you want. It won't define the member function by the same name within the Graph class. Rather, it will declare and define a new free function called printEdge.
This is good and proper, if by your point of view a bit of a pain, because you just might want two functions with the same name but in different scopes. Consider:
// Header File
class A
{
void foo();
};
class B
{
void foo();
};
void foo();
// Implementation File
void foo()
{
}
Which scope should the definition apply to? C++ does not restrict you from having different functions with the same names in different scopes, so you have to tell the compiler what function you're defining.
//yes it is possible using preprocessor like this:
#define $ ClassName //in .cpp
void $::Method1()
{
}
//or like this: in the header .h:
#undef $
#define $ ClassName'
// but you have to include the class header in last #include in your .cpp:
#include "truc.h"
#include "bidule.h" ...
#include "classname.h"
void $::Method() { }
//i was using also
#define $$ BaseClass
//with single inheritance than i can do this:
void $::Method()
{
$$::Method(); //call base class method
}
//but with a typedef defined into class like this it's better to do this:
class Derived : Base
{
typedef Base $$;
}
EDIT: I misread your question. This would be an answer to the question whether you can split header-files. It doesn't help you to avoid using LongClassName::-syntaxes, sorry.
The simple answer: You can split up c++-file, but you can not split up header-files.
The reason is quite simple. Whenever your compiler needs to compile a constructor, it needs to know exactly how many memory it needs to allocate for such an object.
For example:
class Foo {
double bar; //8 bytes
int goo; //4 bytes
}
new Foo() would require the allocation of 12 bytes memory. But if you were allowed to extend your class definitions over multiple files, and hence split header files, you could easily make a mess of this. Your compiler would never know if you already told it everything about the class, or whether you did not. Different places in your code could have different definitions of your class, leading to either segmentation faults or cryptic compiler errors.
For example:
h1.h:
class Foo {
double bar; // 8 bytes
int goo; // 4 bytes
}
h2.h:
#include "h1.h"
class Foo {
double goo; // 8 bytes
} // we extend foo with a double.
foo1.cpp:
#include "foo1.h"
Foo *makeFoo() {
return new Foo();
}
foo2.cpp:
#include "foo2.h"
void cleanupFoo(Foo *foo) {
delete foo;
}
foo1.h:
#include "h1.h"
Foo *makeFoo();
foo2.h:
#include "h1.h"
#include "h2.h"
void cleanupFoo(Foo *foo)
main.cpp:
#include foo1.h
#include foo2.h
void main() {
Foo *foo = makeFoo();
cleanupFoo(foo);
}
Carefully check what happens if you first compile main.cpp to main.o, then foo1.cpp to foo1.o and foo2.cpp to foo2.o, and finally link all of them together. This should compile, but the makeFoo() allocates something else then the cleanupFoo() deallocated.
So there you have it, feel free to split .cpp-files, but don't split up classes over header files.
While trying to make a simple game, I've run in to a circular dependency problem.
I searched on the internet and found that forward declaring could fix it, but... Both of my classes depend on a static value.
Is there any easy way to fix, perhaps to forward declare the static values, or do I have to rewrite the core of my game?
2ND EDIT: Looks like I was wrong, the error's still there even after removing almost everything:
main.cpp:
#include "App.h"
//Start the app
int main(int argc, char* args[]){
App App;
return App.on_execute();
}
App.h:
#ifndef APP_H
#define APP_H
#include "Object.h"
class App
{
public:
//Runs when the program starts
int on_execute();
};
#endif // APP_H
App.cpp:
#include "App.h"
int App::on_execute(){
return 0;
}
Object.h:
#ifndef OBJECT_H
#define OBJECT_H
#include <string>
#include <vector>
#include <stdio.h>
#include <SDL.h>
#include <math.h>
#include "Entity.h"
class Object
{
public:
Object(int character, int x, int y, std::string name, SDL_Color color, bool blocks);
//Object vector
static std::vector<Object*> objects;
};
#endif // OBJECT_H
Object.cpp:
#include "Object.h"
std::vector<Object*> Object::objects;
Object::Object(int character, int x, int y, std::string name, SDL_Color color, bool blocks){
}
Entity.h:
#ifndef ENTITY_H
#define ENTITY_H
#include "Object.h"
#include <sdl.h>
class Entity : public Object
{
public:
Entity(int character, int x, int y, std::string name, SDL_Color color, bool blocks, int hp, int power, int defense);
};
#endif // ENTITY_H
Entity.cpp:
#include "Entity.h"
Entity::Entity(int character, int x, int y, std::string name, SDL_Color color, bool blocks, int hp, int power, int defense) : Object(character, x, y, name, color, blocks){
}
I think the design of your code may need to be reworked.
First of all, I'd really discourage you from using non-primitive, non-trivial class statics where possible, whether class static or global static. Non-trivial static classes will have an explicit constructor call before main, and will need to register a destruction to be called after main. The relative ordering of these things is undefined. Worse, if you have a library structure later such that the assembly from the same .cpp file shows up twice, weird things can happen where two copies of the object get constructed, but the same one is destroyed twice.
Second, some of the information is unclear. For example, you claim that the Map class has a static member of type Map. I really don't think this is possible; the static Map member will also have an object of type map, and so on. Similarly with the vector of Objects declared inside Object. Maybe in both these cases you mean inside the file Map.cpp or Object.cpp, as opposed to literally inside the class?
Third, be clear on what forward declaration gives you. It makes the compile aware that something exists, nothing more. It lets you have pointers and references to that type. You cannot create an object or even declare a member variable of a forward declared type, because the compiler doesn't know the size of the forward declared object. You can't use its methods because the compiler doesn't know they exist.
Fourth, you didn't talk about your header files at all. It's only a circular dependency if Map.h requires Object.h, and vice versa. Two header files can't both include each other. On the other hand, the implementation is in Map.cpp and Object.cpp, both of these files can include both Map.h and Object.h. However, personally I prefer to avoid having mutually dependent classes.
What I'd probably suggest is that a Map should own the Objects present on that map. The pattern right now with Map accessing this global is not a good one. Instead of having objects be a global, make std::vector objects a member of the Map class. Notice that if you decide to have multiple Maps later, this works much better, each Map will own the Objects located on that map. The current design doesn't work well if there's more than one Map.
You can then implement move_to as a method not of Object, but rather of Map. Map::move_to(i, dx, dy) moves the ith Object.
I know this has been posted plenty of times before, but none of the solutions were able to help. I'm trying to create multiple subclasses from one superclass (in this instance, Value->Fraction->RationalFraction and Value->Fraction->IrrationalFraction), but I keep getting this error. I assume it's from a circular inclusion, but I don't know how to make the Fraction code work without it. When I construct Fraction, depending on the constructor, it creates an Irrational or Rational Fraction, but then I need to include Fraction in those subclasses, and it kind of creates a cluster. The error is coming in RationalFraction and IrrationalFraction, and I can't seem to get around it. Is there a smoother way to implement this or at the least a way to fix the error? Sorry if this has been answered already, I'm still new to polymorphism.
Value.h
#ifndef VALUE_H
#define VALUE_H
#include <string>
using namespace std;
class Value
{
public:
Value();
virtual ~Value();
string type;
virtual string getType() = 0;
protected:
private:
virtual Value* simplify() = 0;
};
#endif // VALUE_H
Fraction.h
#ifndef FRACTION_H
#define FRACTION_H
#include "Value.h"
#include "RationalFraction.h"
#include "IrrationalFraction.h"
#include <string>
using namespace std;
class Fraction: public Value
{
private:
RationalFraction* rtF;
virtual Fraction* simplify() = 0;
IrrationalFraction* irF;
public:
Fraction(int n, int d);
Fraction(string n, int d);
virtual ~Fraction();
virtual string getType() = 0;
int numer;
int denom;
protected:
};
#endif // FRACTION_H
Fraction.cpp
#include "Fraction.h"
#include <iostream>
using namespace std;
Fraction::Fraction(int n, int d) {
rtF = new RationalFraction(n,d);
}
Fraction::Fraction(string n, int d){
irF = new IrrationalFraction(n, d);
}
Fraction::~Fraction()
{
delete rtF;
delete irF;
}
IrrationalFraction.h
#ifndef IRRATIONALFRACTION_H
#define IRRATIONALFRACTION_H
class IrrationalFraction : public Fraction
{
public:
IrrationalFraction(string n, int d);
virtual ~IrrationalFraction();
protected:
private:
IrrationalFraction* simplify();
};
#endif // IRRATIONALFRACTION_H
RationalFraction.h
#ifndef RATIONALFRACTION_H
#define RATIONALFRACTION_H
using namespace std;
class RationalFraction: public Fraction
{
public:
RationalFraction(int n, int d);
virtual ~RationalFraction();
int numer;
int denom;
protected:
private:
RationalFraction* simplify();
};
#endif // RATIONALFRACTION_H
Thanks guys!
Here's the error message:
include\RationalFraction.h|8|error: expected class-name before '{' token|
include\IrrationalFraction.h|5|error: expected class-name before '{' token|
||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|
1 First of all you need to replace the includes of RationalFraction.h and IrrationalFraction.h with forward class declarations, like this:
class RationalFraction;
class IrrationalFraction;
2 Second, you need to add those includes in file Fraction.cpp.
3 Third, you need to add includes of Fraction.h in RationalFraction.h and IrrationalFraction.h.
4 Fourth, you need to add implementations of getType in both those classes.
5 Fifth, to avoid serious problems with name collisions and such, you need to remove using namespace std; from the headers.
6 Sixth, to avoid double deletions, which is Undefined Behavior, you have to either disallow copying, or handle copying. One way to handle copying is to use smart pointers instead of raw pointers. Another is to define copy constructor and copy assignment operator (that's a bit over-simplified, but you can easily find the details: google for "rule of three").
7 The constructor of Fraction unconditionally calls the constructor of IrrationalFraction, which calls the constructor of Fraction. This is an infinite recursion which must be resolved some way. You'll find that when you start testing.
The design here looks very Java-esque.
Have you considered class templates?
Line 8 of RationalFraction.h says
class RationalFraction: public Fraction
but there's no Fraction declared anywhere in that file. You have to
#include "Fraction.h"
if you plan to use things declared within.
Note that Fraction.h includes RationalFraction.h iteslf. If you don't fix that, you will have a case of circular header dependencies problem, which basically means noithing will work. You probably want to use forward declarations of RationalFraction and IrrationalFraction instead of including their headers.
I don't think your design is very good, but apart form that, there are some obvious issues:
1 your using names that have not been declared, such Fraction in RationalFraction.h.
2 you can use a pointer to an object (like RationalFraction* rtF;) without a definition of the object: all you need is a declaration.
You miss some "#include"s.
When you implement inheritance, the compiler expect that you will Inherit from class. And the compiler don't know "Fraction" is a class, because you dont include his .h file
you can't have classes like RationalFraction and Fraction that embed each others. You should use a technique called forward declaration (What are forward declarations in C++?). In few words, this means that you can declare two classes RationalFraction and IrrationalFraction like below, without include the two headers file. What you need is simply keep two pointers to these classes, so the pointers size is fixed and know by the compiler (4 or 8 bytes, depends by your PC's processor architecture).
#ifndef FRACTION_H
#define FRACTION_H
#include "Value.h"
#include <string>
using namespace std;
class RationalFraction;
class IrrationalFractional;
class Fraction: public Value
{
private:
RationalFraction* rtF;
virtual Fraction* simplify() = 0;
IrrationalFraction* irF;
public:
...
...
};
You must include Fraction.h in RationalFraction.h and IrrationalFraction.h. Additionally, when you include RationalFraction.h and IrrationalFraction.h in Fraction.h, the compiler happens to find the class declaration
class RationalFraction: public Fraction
before having seen the declaration of Fraction. You can only use fully declared classes as base-classes. You could solve this with forward declaring RationalFraction and IrrationalFraction in Fraction.h:
#ifndef FRACTION_H
#define FRACTION_H
#include "Value.h"
#include <string>
using namespace std;
class RationalFraction;
class IrrationalFraction;
class Fraction: public Value
{
private:
RationalFraction* rtF;
virtual Fraction* simplify() = 0;
IrrationalFraction* irF;
public:
Fraction(int n, int d);
Fraction(string n, int d);
virtual ~Fraction();
virtual string getType() = 0;
int numer;
int denom;
protected:
};
#endif // FRACTION_H
This informs the compiler that there are classes RationalFraction and IrrationalFraction. You can not do very much with forward-declared types because the compiler does not know anythign about the class, especially the object's size. But what you can do is delcare pointers and references to them, so for Fraction this would be enough.
I am not sure what happens in Fraction::Fraction when you instantiate the subclasses in the base-class constructor. My guess would be that this is an infinite recursion. I guess you want something like a factory, but it does not work this way.
I'm writing an integral calculator. I'm trying to get the main.cpp file to read in the functions from the functions class which is in the functions.h.cpp files. I have a function defined as the following for the easy case:
double square(double aX)
{
return aX*aX;
}
This function works when I include it in the main file, though it doesn't want to work when I try and call it from the main file when it's in the functions file. Here is the code that I have:
Main.cpp file:
#include <iostream>
#include "IntegralCalculator.h"
#include "functions.h"
using namespace std;
int main()
{
IntegralCalculator Function(square);
Function.print();
}
As you can see, there is another class called IntegralCalculator which actually does the calculation of the integral, though nothing should be wrong with that as it works when the function definition is included in the main, and the function is passed as a parameter. The functions.h file is defined as the following:
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
#include <iostream>
#include <cmath>
#include "IntegralCalculator.h"
class functions : public IntegralCalculator
{
public:
functions();
double square(double aX);
};
#endif
and the functions.cpp file is defined as such:
#include <iostream>
#include <cmath>
#include "functions.h"
double functions::square(double aX)
{
return aX*aX;
}
I know that as of right now I don't need the <cmath> library, though I'm going to need it for more complicated functions when I add them.
I have tried inheriting the functions class in the main, and I have tried creating a namespace for the functions class and defining the function, however none of these have worked. When I go to compile, I get the following error:
Main.cpp: In function ‘int main()’:
Main.cpp:9: error: ‘square’ was not declared in this scope
If someone could please help me figure out this problem. This code that I'm trying to write is more advanced than my class has gone over, so I'm not sure how to fix it, though I want to write the program this way.
Edit: In case you were curious, I am including the functions.h and functions.cpp files in the Makefile. I was getting the same error when I was trying to put the square(double aX) definition in the IntegralCalculator class as well.
Your problem is, square is a member function AKA method. In other words, there is no plain symbol square anywhere, it's functions::square. And because it is not a static method, it makes no sense alone, it always needs a corresponding object instance, which you do not have and which IntegralCalculator couldn't use even if you did.
3 solutions, in the order of simplest, closest to your question, best:
From the constructor delcaration, move the square out of the class, make it a global function:
In functions.h outside any class:
double square(double aX);
In functions.cpp
double square(double aX) {
return aX*aX;
}
Usage in main.cpp:
IntegralCalculator Function(square);
Or make it static method (which is how you would have to do if you used a language like Java, which didn't allow "naked" functions, but is not really C++ way):
in functions.h:
class functions // inheriting IntegralCalculator removed as not needed
{
public:
static double square(double aX);
};
and in functions.cpp:
//static
double functions::square(double aX) {
return aX*aX;
}
Then you can pass it like this to `Function constructor in main.cpp:
IntegralCalculator Function(functions::square);
Finally, perhaps the best solution, sort of combining the best of the two above: put square in a namespace. So functions.h becomes
namespace functions {
double square(double aX)
}
functions.cpp becomes
namespace functions {
double square(double aX) {
return aX*aX;
}
}
You still use it in main like this:
IntegralCalculator Function(functions::square);
You have:
class functions : public IntegralCalculator
{
public:
functions();
double square(double aX);
};
which is ok, but doesn't tell other cpp files that there is a global function called square somewhere in your functions.cpp file.
What you need to do is include the header for that function so that the compiler knows that it exists:
double square(double ax);
class functions : public IntegralCalculator
{
public:
functions();
double square(double aX);
};
Also completely unrelated to your question, but worth mentioning after seeing your constructor code, you might want to use a typedef to declare the function pointer like so:
typedef double (IntegralFunctor*)(double);
So that your constructor can now be
IntegralCalculator::IntegralCalculator(IntegralFunctor func);
It's cleaner and less confusing this way
Is there a way to avoid the Graph:: repetition in the implementation file, yet still split the class into header + implementation? Such as in:
Header File:
#ifndef Graph_H
#define Graph_H
class Graph {
public:
Graph(int n);
void printGraph();
void addEdge();
void removeEdge();
};
#endif
Implementation File:
Graph::Graph(int n){}
void Graph::printGraph(){}
void Graph::addEdge(){}
void Graph::removeEdge(){}
I'm guessing this is to avoid lots of "unnecessary typing". Sadly there's no way to get rid of the scope (as many other answers have told you) however what I do personally is get the class defined with all my function prototypes in nice rows, then copy/paste into the implementation file then ctrl-c your ClassName:: on the clip board and run up the line with ctrl-v.
If you want to avoid typing the "Graph::" in front of the printGraph, addEdge etc., then the answer is "no", unfortunately. The "partial class" feature similar to C# is not accessible in C++ and the name of any class (like "Graph") is not a namespace, it's a scope.
No there's not. Not directly at least. You could go for preprocessor tricks, but don't do it.
#define IMPL Graph::
IMPL Graph(int n){}
void IMPL printGraph(){}
void IMPL addEdge(){}
void IMPL removeEdge(){}
Also, you shouldn't even want to do it. What's the point. Besides it being a C++ rule, it lets you know you're actually implementing a member function.
One option is using. If you have method definitions which are in a cpp file that never gets #included, then using is safe (doesn't affect other files):
foo.h:
class FooLongNameSpecialisationsParamaters
{
int x_;
public:
int Get () const;
void Set (int);
};
foo.cpp:
#include "foo.h"
using Foo = FooLongNameSpecialisationsParamaters;
int Foo::Get () const
{
return x_;
}
void Foo::Set (int x)
{
x_ = x;
}
main.cpp:
#include "foo.h"
int main ()
{
//Foo foo; <-- error
FooLongNameSpecialisationsParamaters foo;
return 0;
}
No, there is no way to avoid it. Otherwise, how would you know if a given function definition is for a class function or for a static function?
If you are asking if you can define a member function such as Graph::printGraph without specifying the class name qualification, then the answer is no, not the way that you want. This is not possible in C++:
implementation file:
void printEdge(){};
The above will compile just fine, but it won't do what you want. It won't define the member function by the same name within the Graph class. Rather, it will declare and define a new free function called printEdge.
This is good and proper, if by your point of view a bit of a pain, because you just might want two functions with the same name but in different scopes. Consider:
// Header File
class A
{
void foo();
};
class B
{
void foo();
};
void foo();
// Implementation File
void foo()
{
}
Which scope should the definition apply to? C++ does not restrict you from having different functions with the same names in different scopes, so you have to tell the compiler what function you're defining.
//yes it is possible using preprocessor like this:
#define $ ClassName //in .cpp
void $::Method1()
{
}
//or like this: in the header .h:
#undef $
#define $ ClassName'
// but you have to include the class header in last #include in your .cpp:
#include "truc.h"
#include "bidule.h" ...
#include "classname.h"
void $::Method() { }
//i was using also
#define $$ BaseClass
//with single inheritance than i can do this:
void $::Method()
{
$$::Method(); //call base class method
}
//but with a typedef defined into class like this it's better to do this:
class Derived : Base
{
typedef Base $$;
}
EDIT: I misread your question. This would be an answer to the question whether you can split header-files. It doesn't help you to avoid using LongClassName::-syntaxes, sorry.
The simple answer: You can split up c++-file, but you can not split up header-files.
The reason is quite simple. Whenever your compiler needs to compile a constructor, it needs to know exactly how many memory it needs to allocate for such an object.
For example:
class Foo {
double bar; //8 bytes
int goo; //4 bytes
}
new Foo() would require the allocation of 12 bytes memory. But if you were allowed to extend your class definitions over multiple files, and hence split header files, you could easily make a mess of this. Your compiler would never know if you already told it everything about the class, or whether you did not. Different places in your code could have different definitions of your class, leading to either segmentation faults or cryptic compiler errors.
For example:
h1.h:
class Foo {
double bar; // 8 bytes
int goo; // 4 bytes
}
h2.h:
#include "h1.h"
class Foo {
double goo; // 8 bytes
} // we extend foo with a double.
foo1.cpp:
#include "foo1.h"
Foo *makeFoo() {
return new Foo();
}
foo2.cpp:
#include "foo2.h"
void cleanupFoo(Foo *foo) {
delete foo;
}
foo1.h:
#include "h1.h"
Foo *makeFoo();
foo2.h:
#include "h1.h"
#include "h2.h"
void cleanupFoo(Foo *foo)
main.cpp:
#include foo1.h
#include foo2.h
void main() {
Foo *foo = makeFoo();
cleanupFoo(foo);
}
Carefully check what happens if you first compile main.cpp to main.o, then foo1.cpp to foo1.o and foo2.cpp to foo2.o, and finally link all of them together. This should compile, but the makeFoo() allocates something else then the cleanupFoo() deallocated.
So there you have it, feel free to split .cpp-files, but don't split up classes over header files.