I have some simple codes here:
// main.cpp
#include <iostream>
#include "foo.h"
int main() {
Foo foo;
foo.spam();
std::cout << "In main: sizeof (Foo) = " << sizeof (Foo) << std::endl;
return 0;
}
// foo.h
#ifndef FOO_H
#define FOO_H
class Foo {
public:
int bar;
void spam();
};
#endif
// foo.cpp
#include <iostream>
#include "foo.h"
void Foo::spam() {
std::cout << "sizeof (Foo) = " << sizeof (Foo) << std::endl;
}
The program is simple and we can easily foresee the output:
sizeof (Foo) = 4
In main: sizeof (Foo) = 4
But as for the include directives, the preprocessor simply replace them with the included file content, so the declaration of Foo appears in both main.cpp and foo.cpp.
What if we manually put the declaration of Foo in main.cpp and modify it on purpose like this?
// main.cpp
#include <iostream>
// #include "foo.h" replaced with declaration of foo
#ifndef FOO_H
#define FOO_H
class Foo {
public:
int bar, baz, qux, eggs; // added some members
void spam();
};
#endif
int main() {
Foo foo{111, 222, 333, 444};
foo.spam();
std::cout << "In main: sizeof (Foo) = " << sizeof (Foo) << std::endl;
std::cout << "foo.qux = " << foo.qux << std::endl; // try to access the newly added qux member
return 0;
}
Now the two declarations of Foo in main.cpp and foo.cpp are different, but the program still compiles and runs! The output becomes
sizeof (Foo) = 4
In main: sizeof (Foo) = 16
foo.qux = 333
What the hell is happening here?! Why can Foo have two different declarations in one program? Why this even compiles?