The basic lesson: Includes are processed before any C++ is parsed. They're handled by the pre-compiler.
Let's say that A.h
winds up being included prior to B.h
. You get something like this:
#ifndef A_H
#define A_H
// ----- B.h include -----
#ifndef B_H
#define B_H
#include "A.h" // A_H is defined, so this does nothing
struct B {
int b;
};
void doStuff2 (A a); // Error here
#endif
// ----- B.h include -----
struct A {
int a;
};
void doStuff1 (B b); // Error here
#endif
At this point, the C++ compiler can take over and start parsing things out. It will try to figure out what the parameter to doStuff2
is, but A
hasn't been defined yet. The same logic holds true going the other way. In both cases, you have dependencies on types that haven't been defined yet.
All of this just means that you have your dependencies out of order. It isn't a problem with pass-by-value. Your types must be defined prior to your methods. That's all - see the example below.
// Example program
#include <iostream>
#include <string>
// data_types.h
struct A
{
int x;
};
struct B
{
int y;
};
using namespace std;
// methods_A.h
void foo(A a)
{
a.x = 3;
cout << "a: " << a.x << endl;
}
// methods_B.h
void bar(B b)
{
b.y = 4;
cout << "b: " << b.y << endl;
}
int main()
{
A first;
B second;
first.x = 0;
second.y = 100;
foo(first);
bar(second);
cout << "A: " << first.x << ", B: " << second.y << endl;
}
Example output
a: 3
b: 4
A: 0, B: 100