I\'m an old (but not too old) Java programmer, that decided to learn C++. But I have seen that much of C++ programming style, is... well, just damn ugly!
All that stuff
In addition to what others have said here, there are even more important problems:
1) Large translation units lead to longer compile times and larger object file sizes.
2) Circular dependencies! And this is the big one. And it can almost always be fixed by splitting up headers and source:
// Vehicle.h
class Wheel {
private:
Car& m_parent;
public:
Wheel( Car& p ) : m_parent( p ) {
std::cout << "Car has " << m_parent.numWheels() << " wheels." << std::endl;
}
};
class Car {
private:
std::vector< Wheel > m_wheels;
public:
Car() {
for( int i=0; i<4; ++i )
m_wheels.push_back( Wheel( *this ) );
}
int numWheels() {
return m_wheels.size();
}
}
No matter what order you put these in, one will always be lacking the definition of the other, even using forward declarations it won't work, since in the function bodies are using specifics about each class's symbol.
But if you split them up into proper .h and .cpp files and use forward declarations it will satisfy the compiler:
//Wheel.h
//-------
class Car;
class Wheel {
private:
Car& m_parent;
public:
Wheel( Car& p );
};
//Wheel.cpp
//---------
#include "Wheel.h"
#include "Car.h"
Wheel::Wheel( Car& p ) : m_parent( p ) {
std::cout << "Car has " << m_parent.numWheels() << " wheels." << std::endl;
}
//Car.h
//-----
class Wheel;
class Car {
private:
std::vector< Wheel > m_wheels;
public:
Car();
int numWheels();
}
//Car.cpp
//-------
#include "Car.h"
#include "Wheel.h"
Car::Car() {
for( int i=0; i<4; ++i )
m_wheels.push_back( Wheel( *this ) );
}
int Car::numWheels() {
return m_wheels.size();
}
Now the code that actually has to know specifics about the second class can just include the header file which doesn't need to know specifics about the first class.
Headers just provide the declarations while source files provide the definitions. Or another way to say it: Headers tell you what is there (what symbols are valid to use) and source tells the compiler what the symbols actually do. In C++ you don't need anything more than a valid symbol to begin using whatever it is.
Trust that C++ has a reason for this idiom, because if you don't you will make a lot of headaches for yourself down the line. I know :/