Parallell struct dependancy in C++

R

royend

Hi.
I am having trouble with the definition of my two structs in C++. Both
have functions depending on each other, which means none of them can
be declared before the other. How may I solve this?

A quick example:
struct structA{
int x;
void functionA(structB);
}

struct structB{
int y;
void functionB(structA);
}

This produces an error for structA, because it is missing a
declaration of structB. But, declaring structB before structA, just
turns the problem around as structB then will be missing a declaration
of structA...

Do you know of any possible solutions?
 
S

Salt_Peter

Hi.
I am having trouble with the definition of my two structs in C++. Both
have functions depending on each other, which means none of them can
be declared before the other. How may I solve this?

A quick example:

you need a forward declaration here, as detailed in FAQ:
[39.11] How can I create two classes that both know about each other?
http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.11
struct structA{
int x;
void functionA(structB);

}

thats not a valid declaration, missing semicolon
struct structB{
int y;
void functionB(structA);

}

This produces an error for structA, because it is missing a
declaration of structB. But, declaring structB before structA, just
turns the problem around as structB then will be missing a declaration
of structA...

Do you know of any possible solutions?

#include <iostream>

class B; // forward declaring an incomplete type

struct A {
int x;
void function( const B& );
};

void A::function( const B& r_b )
{
std::cout << "A::function(const B& r_b)\n";
}

struct B {
int y;
void function( const A& );
};

void B::function( const A& r_a )
{
std::cout << "B::function(const A& r_a)\n";
}

int main()
{
A a;
B b;
b.function( a );
}
 
?

=?ISO-8859-1?Q?Erik_Wikstr=F6m?=

Hi.
I am having trouble with the definition of my two structs in C++. Both
have functions depending on each other, which means none of them can
be declared before the other. How may I solve this?

A quick example:
struct structA{
int x;
void functionA(structB);
}

struct structB{
int y;
void functionB(structA);
}

This produces an error for structA, because it is missing a
declaration of structB. But, declaring structB before structA, just
turns the problem around as structB then will be missing a declaration
of structA...

Do you know of any possible solutions?

Forward declarations and pointers:

You start by telling the compile that there exists a structure named
structB but you don't tell it anything about it (this is the forward
declaration), then you declare structA, but with the modification that
the function takes a pointer to a structB. And finally you declare structB:

struct structB;

struct structA{
int x;
void functionA(structB*);
}; // Dont forget the ;

struct structB{
int y;
void functionB(structA);
};
 
M

Michael

Forward declarations and pointers:

There's no need to switch to pointers to fix this problem (although
there might be other, unrelated reasons to use pointers).

When you *declare* a method, if the parameters and return types are
pointers, references, or the classes/structs themselves doesn't
matter. You don't need the definitions. You only need the
definitions where you use the class. That would include the method
definitions and the call site.

The simple solution to the OP's problem is this:
1) Declare classes, structs, and their methods in .h files.
2) Define methods in .cpp or .cc files only, not in .h files.
3) Forward declare classes as needed in the .h files.
4) Have the .cpp files #include both .h files.

All the best.
Michael
 
X

xman

This produces an error for structA, because it is missing a
declaration of structB. But, declaring structB before structA, just
turns the problem around as structB then will be missing a declaration
of structA...

Do you know of any possible solutions?

Use forward declaration like:
class A;
class B;

class A { ... };
class B { ... };

However, you'll also need to use pointer to reference the other
classes.
 
M

Michael

However, you'll also need to use pointer to reference the other
classes.

Not true. This is a very common misconception (two people have posted
it so far), but it is simply not correct. See my previous post.

Michael
 
S

Salt_Peter

Forward declarations and pointers:

You start by telling the compile that there exists a structure named
structB but you don't tell it anything about it (this is the forward
declaration), then you declare structA, but with the modification that
the function takes a pointer to a structB. And finally you declare structB:

There is a certain level of confusion here. Using the pointer (or
better - a reference / const reference) only prevents invoking copy
construction once the function is called. It serves no other purpose.
The use of pointer/reference is only required to prevent circular
redundancy in the case one class is a member of the other and vice
versa.

example:

struct B;
struct A
{
B m_b;
};

struct B
{
A m_a;
};

int main()
{
B b; // the compiler is unable to calculate the size of type B
}

An A has a B which has an A which has a B ... to infinity
That scenario is *not* one that the OP suffers from.
 
S

Salt_Peter

Use forward declaration like:
class A;
class B;

class A { ... };
class B { ... };

However, you'll also need to use pointer to reference the other
classes.

No he doesn't. He can use whatever he finds appropriate for his needs.
The OP is dealing with parameters to member functions, not members of
the class(es). As an example, consider primitives, he may very well
decide not to use a pointer or reference because his tests show better
results are achieved by copying the primitive. Here is an example.

#include <iostream>

struct B;

struct A {
int n;
A(int n_) : n(n_) { std::cout << "A()\n"; }
A(const A& copy)
{
std::cout << "copy A\n";
n = copy.n;
}
void function( const B ); // by value
};

struct B {
int n;
void function( const A ); // by value
};

void A::function( const B b )
{
n = b.n;
}

void B::function( const A a )
{
n = a.n;
}

int main()
{
A a(99);
B b;
b.function( a );
std::cout << b.n << std::endl;
}

/*
A()
copy A // fast copy
99
*/

Again, the only reason to use a pointer or reference or const
reference is if the instance being passed as a parameter has a
performance hit if_and_when a copy ctor is invoked. Thats is not the
Op's situation, he is *not* suffering from circular membership /
redundancy.
 
X

xman

There's no need to switch to pointers to fix this problem (although
there might be other, unrelated reasons to use pointers).

Got it :) I replied before I was able to see this post.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,780
Messages
2,569,607
Members
45,240
Latest member
pashute

Latest Threads

Top