n00b class question

T

thekestrel

Why can't I create an instance of A and B in the Class C definition?

#include <iostream>

class B;
class A;

class C {
public:
B b;
A a;
};

class B {
int b;
};

class A {
int a;
};

int main (void)
{
C c;

return 0;
}
 
V

Victor Bazarov

Why can't I create an instance of A and B in the Class C definition?

#include <iostream>

class B;
class A;

class C {
public:
B b;
A a;
};

To understand how to construct an instance of C, the compiler needs to
know what the internal structures of 'B' and 'A' are. Since you didn't
define (only declared) the classes 'B' and 'A' before 'C', the compiler
cannot do what it needs. Move the definition of 'C' _after_ 'B' and 'A'
definitions.
class B {
int b;
};

class A {
int a;
};

int main (void)
{
C c;

return 0;
}

V
 
T

thekestrel

Kavya said:
Because class A and B are not yet defined.

Thanks for the reply,
I thought that the

class B;
class A;

at the start essentially helped the compiler know the rest of the
definition would be later on?How can I have it know about the
definition of A and B whilst still having them listed after C? (for a
more complicated problem which essentially means A contains B and B
contains A so reordering would not fix it.

AwooOOoo
 
S

Scott McPhillips [MVP]

Thanks for the reply,
I thought that the

class B;
class A;

at the start essentially helped the compiler know the rest of the
definition would be later on?How can I have it know about the
definition of A and B whilst still having them listed after C? (for a
more complicated problem which essentially means A contains B and B
contains A so reordering would not fix it.

AwooOOoo

You cannot put B and C members in A unless B and C are defined first.
One reason is very fundamental: The compiler must know their size in
order to make them part of C.

You can, however, put pointers to B and C in A. The compiler knows what
size a pointer is :)
 
V

Victor Bazarov

I thought that the

class B;
class A;

at the start essentially helped the compiler know the rest of the
definition would be later on?

You seem to be asking a question here. The answer is "yes, you do
seem to have thought that".
How can I have it know about the
definition of A and B whilst still having them listed after C?

"How can I have my cake and eat it too?"
(for a
more complicated problem which essentially means A contains B and B
contains A so reordering would not fix it.

The closing parenthesis is missing.

This is precisely the point. The compiler has to know the sizes of
the objects A and B so it can generate proper code. This is the
requirement of the language, mostly so that the compilers don't have
to be too sophisticated (which often means unimplementable).

V
 
T

thekestrel

Scott said:
You cannot put B and C members in A unless B and C are defined first.
One reason is very fundamental: The compiler must know their size in
order to make them part of C.

You can, however, put pointers to B and C in A. The compiler knows what
size a pointer is :)


Makes Sense. The example I'm playing with is to get familiar with
templates and the calling that I was trying to simplify is better
represented by,

template <class T>
class Balls {
public:
list<Sticks<T> *> s;
}

template <class T>
class Sticks {
public:
list<Balls<T> *> b;
}

So I want a list of pointers to the other templated class. I think this
means that I end up with a similar problem to what you described as s
and b are not pointers so the compiler doesn't know the size of the
list inside the class. Any thoughts on how to get around this? The idea
in the mock up would be that each class could contain a list of
pointers to the other class.

Appreciate your thoughts.

AwooOOoo.
 
K

Kai-Uwe Bux

Thanks for the reply,
I thought that the

class B;
class A;

at the start essentially helped the compiler know the rest of the
definition would be later on?How can I have it know about the
definition of A and B whilst still having them listed after C? (for a
more complicated problem which essentially means A contains B and B
contains A so reordering would not fix it.

You cannot have that. You will have to break the cycle by using an A* in B
or a B* in A (that is something for which a forwar declaration suffices!).

Think about it:

struct A {
int i;
B b;
};

struct B {
int j;
A a;
};

and ask yourself: will we have sizeof(A) < sizeof(B) because of the b in A
or will we have sizeof(B) < sizeof(A) because of the a in B? Obviously, you
would have both, which is a contradiction. Thus, you cannot do it.


Best

Kai-Uwe Bux
 
S

Salt_Peter

Why can't I create an instance of A and B in the Class C definition?

#include <iostream>

class B;
class A;

class C {
public:
B b;
A a;
};

class B {
int b;
};

class A {
int a;
};

int main (void)
{
C c;

return 0;
}

The above is expected unless you use pointers or references to A,B in
class C.
This should still be a minor issue since each class above will probably
end up being declared in its own header and implemented in its own
source file. At least, that is what your goal should be once you have
the skeleton up and running.
As in...

/* ___ c.hpp ___ class C interface declaration */
#ifndef C_HPP_
#define C_HPP_ /* include guard */

#include "a.hpp"
#include "b.hpp"

class C
{
A a;
B b;
public:
C(); // def ctor
};

#endif /* include guard C_HPP_ */

/* ___ c.cpp ___ class C implementation */
#include "c.hpp"

// def ctor
C::C() : a(0), b(0)
{
}
 
H

Howard

Makes Sense. The example I'm playing with is to get familiar with
templates and the calling that I was trying to simplify is better
represented by,

template <class T>
class Balls {
public:
list<Sticks<T> *> s;
}

template <class T>
class Sticks {
public:
list<Balls<T> *> b;
}

So I want a list of pointers to the other templated class. I think this
means that I end up with a similar problem to what you described as s
and b are not pointers so the compiler doesn't know the size of the
list inside the class.

No, that's not a problem. You're declaring a list which will hold pointers,
which is fine. The list size is dynamic; it grows when you add items to it.

Is that the actual code you have?

One problem is that you're missing semicolons (;) after the class
definitions. Also, you'd need to forward declare "template <class T> class
Sticks;" before the Balls class. The it will compile fine.

But how do you try to use this code? What's T?

You could easily have code like this:

Sticks<Balls<int> > ballsticks;
Balls<Sticks<int> > stickballs;

Is that the kind of thing you meant to do?

-Howard
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top