Hi,
I was trying to implement a composition relation, somthing of the
following type:
class A
{
public:
class B
{
int member_of_B;
};
B b;
// ... some other members;
};
but as the defintion of B is too large I thought of may be writing it
outside. ;). So i modified the class as:
class A
{
class B;
B b;
....
};
class B {
int member_of_B;
};
We have two issues here:
1. anybody including "the .h" (in which i have declared the classes)
would get the type B and can use it. which i didn't intend to allow ;).
2. gcc 3.3.2 gave me an error of this type:
error: field `b' has incomplete type
Am I not allowed to use forward referencing ? What exactly does the
statement
class B;
in definition of A do? Doesn't it introduce the typename in A?
Any suggestions? Am I missing something obvious ?
~ M. 11 2630
Milind wrote: Hi,
I was trying to implement a composition relation, somthing of the following type:
class A { public: class B { int member_of_B; };
B b; // ... some other members; };
but as the defintion of B is too large I thought of may be writing it outside. ;). So i modified the class as:
class A { class B; B b; ... };
class B { int member_of_B; };
We have two issues here:
1. anybody including "the .h" (in which i have declared the classes) would get the type B and can use it. which i didn't intend to allow ;).
2. gcc 3.3.2 gave me an error of this type:
error: field `b' has incomplete type
Am I not allowed to use forward referencing ? What exactly does the statement
class B;
in definition of A do? Doesn't it introduce the typename in A?
A couple of misunderstandings here. The correct way to make the forward
declaration is
class B;
class A
{
B b;
};
class B
{
};
Since class B is declared outside of class A, the forward declaration
must also be outside of class A.
But the second misunderstanding is that an incomplete class (which is
what B is between the forward declaration and the actual declaration) is
only good for a very few things, for instance declaring pointers. In you
code the compiler needs to know the size of B in order to generate code
for A, but it does not know the size of B from just the forward declaration.
The obvious solution to this is just to reverse the order in which you
define your classes.
The other solution would be to rewrite A like this
class B;
class A
{
B* b;
};
By using a pointer you would not need to include the definition of B in
the header file at all. This might also help with your other requirement
that B not be usable by itself. Any suggestions? Am I missing something obvious ?
Not obvious, but I'd guess you come from a Java background and haven't
quite absorbed yet that objects in C++ are values not references. Easily
the most fundamental difference between Java and C++.
john
> The correct way to make the forward declaration is
class B;
class A { B b; };
class B { };
Well Even that wont work ;( i copy pasted the above stuff and tried to
compile it with g++ 3.3.2 on my Debian box.
That thing apart,
Since class B is declared outside of class A, the forward declaration must also be outside of class A.
As per my previous posting... 1. anybody including "the .h" .... "which i didn't intend to allow" ;).
I dont want anybody use class B directly, i always want others to use
it as A::B ,i.e as a part of class A. declaring in the way you
suggested will allow everyone else to use it as is.
making it a member would definitely impose using object of class B
inside A's object with this syntax. however, we can't stop ppl from
using bare class B objects. But the second misunderstanding is that an incomplete class (which is what B is between the forward declaration and the actual declaration) is only good for a very few things, for instance declaring pointers.
Yes; pointers work as they have same sizes and we dont allocate memory.
i tried that b4 posting here atfirst and it works fine. that is why i
got confused about forward referencing. if the type is known, why can't
the compiler do a second pass to allocate the mem ?
the compiler needs to know the size of B in order to generate code for A, but it does not know the size of B from just the forward declaration.
that is why i asked: Am I not allowed to use forward referencing ? What exactly does the statement
class B;
in definition of A do? Doesn't it introduce the typename in A?\
i mean doesn't the compiler do a second pass to get the size and
stuff??
The obvious solution to this is just to reverse the order in which you define your classes.
hmmmm ..... but still if i define class B outside class A i will get it
exposed to anyone including the header file. The other solution would be to rewrite A like this
class B;
class A { B* b; };
By using a pointer you would not need to include the definition of B in the header file at all. This might also help with your other requirement that B not be usable by itself.
I dont know how by just declaring a pointer in a class can i restrict
B's usage. could you ellaborate please ?
I did try and implement this with private constructors and friend
functions. However that necessarilly means something else semantically.
i want to implement something like-> A::B always.
Any suggestions? Am I missing something obvious ?
Not obvious
Thnx. cause i was getting pretty worried :)
john
Thnx.
~M
Hey Fabio,
I think the pipl idiom is mostly concerning the avoiding of unnecessary
recompilations and opace interafaces for a class. The example that we
had a couple of days back on the group was regarding the size of a
std::string. i dont exactly believe that the idiom would be useful in
my case.
Thanks.
~M
FabioAng wrote: Probably 'pimpl' idiom can help you:
http://www.gotw.ca/publications/mill04.htm
Bye Fabio
Milind wrote: Hey Fabio,
I think the pipl idiom is mostly concerning the avoiding of unnecessary recompilations and opace interafaces for a class. The example that we had a couple of days back on the group was regarding the size of a std::string. i dont exactly believe that the idiom would be useful in my case.
It would solve *exactly* your requirement of
1. anybody including "the .h" (in which i have declared the classes) would get the type B and can use it. which i didn't intend to allow ;).
--
Karl Heinz Buchegger kb******@gascad.at
Milind wrote: Hi,
I was trying to implement a composition relation, somthing of the following type:
class A { public: class B { int member_of_B; };
B b; // ... some other members; };
but as the defintion of B is too large
Why "too large"? Did you exceed compiler limits?
I thought of may be writing it outside. ;). So i modified the class as:
class A { class B; B b; ... };
class B { int member_of_B; };
We have two issues here:
1. anybody including "the .h" (in which i have declared the classes) would get the type B and can use it. which i didn't intend to allow ;).
Well, this is not really a difference. With your original code, everybody
could declare objects of type B. One would just type A::B instead of B.
Now, you might say that this additional typing effort on part of the user
is exactly what you want to impose (sort of as a forced reminder). Well,
that won't fly either since everybody could just do a
typedef A::B B;
at the begining of their file to get rid of that restriction.
2. gcc 3.3.2 gave me an error of this type:
error: field `b' has incomplete type
Am I not allowed to use forward referencing ? What exactly does the statement
class B;
in definition of A do? Doesn't it introduce the typename in A?
Well, it is a forward declaration inside the scope of A. The compiler should
complain when you do not follow that up by a real declaration inside that
scope.
Also, forward declarations are incomplete. The size of class B is not
deducible from a forward declaration. Thus, the compiler cannot deduce how
much memory is needed for the member object b.
Best
Kai-Uwe Bux
Milind wrote: The correct way to make the forward declaration is
class B;
class A { B b; };
class B { };
Well Even that wont work ;( i copy pasted the above stuff and tried to compile it with g++ 3.3.2 on my Debian box.
Well no, it wasn't intended to work, it only corrects the first of your
errors, not the second. That thing apart,
Since class B is declared outside of class A, the forward declaration must also be outside of class A.
As per my previous posting...
1. anybody including "the .h" .... "which i didn't intend to allow" ;).
I dont want anybody use class B directly, i always want others to use it as A::B ,i.e as a part of class A. declaring in the way you suggested will allow everyone else to use it as is.
OK, well then the only choice you have is to declare B inside of A. making it a member would definitely impose using object of class B inside A's object with this syntax. however, we can't stop ppl from using bare class B objects. But the second misunderstanding is that an incomplete class (which is what B is between the forward declaration and the actual declaration) is only good for a very few things, for instance declaring pointers.
Yes; pointers work as they have same sizes and we dont allocate memory. i tried that b4 posting here atfirst and it works fine. that is why i got confused about forward referencing. if the type is known, why can't the compiler do a second pass to allocate the mem ?
It just doesn't, C++ was designed that way. Makes life easier for the
compiler writers I guess.
john
> OK, well then the only choice you have is to declare B inside of A.
Can i have something like: A::B definition for A? It just doesn't, C++ was designed that way. Makes life easier for the compiler writers I guess.
Oh.. okay.
john
> Why "too large"? Did you exceed compiler limits?
No; BTW, how do you decide on that ??
Well, this is not really a difference. With your original code, everybody could declare objects of type B. One would just type A::B instead of B.
oh. i am sorry, i intended to make B private. Then i am under the
impression that doint something like that is going to make a hell lot
of difference...
First, i dont clutter the namespace in which A is declared. i only have
the defintion of B inside A.
Second, i strictly implement the composition relation, Whenever A dies,
B has to die...
Now, you might say that this additional typing effort on part of the user is exactly what you want to impose (sort of as a forced reminder). Well, that won't fly either since everybody could just do a
typedef A::B B;
Good trick. but i dont intend to impose any typing overheads (because
initially i will be typing more!!) ;) i just dont want ppl to use B as
you have suggested here. The rule is always make a object of A and we
can then create B inside functions of A.
~M
Milind wrote: Why "too large"? Did you exceed compiler limits? No; BTW, how do you decide on that ??
I would trust that the compiler will tell me. Well, this is not really a difference. With your original code, everybody could declare objects of type B. One would just type A::B instead of B.
oh. i am sorry, i intended to make B private. Then i am under the impression that doint something like that is going to make a hell lot of difference...
Yes, if B is private, it makes a *huge* difference.
So, I take it you are just concerned about the file growing a little too
large. Well, you could put the declaration of B inside A and do the
definition afterwards:
#include <iostream>
class A {
class B {
int i;
void print ( void ) const;
};
};
void A::B::print ( void ) const {
std::cout << i << '\n';
}
Of course, this way you can also put the definitions of a B-methods into a
different file.
First, i dont clutter the namespace in which A is declared. i only have the defintion of B inside A.
True.
Second, i strictly implement the composition relation, Whenever A dies, B has to die...
Classes don't die. Objects do. Composition just means that you have an
object of type B as a member of A. It does not mean that there cannot be
any independent B-objects. All member objects of any A-object will die
during the agony of the ambient object. Whether the class B is local or not
is immaterial in this regard.
Best
Kai-Uwe Bux This discussion thread is closed Replies have been disabled for this discussion. Similar topics
17 posts
views
Thread by Dave |
last post: by
|
4 posts
views
Thread by fog |
last post: by
|
10 posts
views
Thread by Florian G. Pflug |
last post: by
|
2 posts
views
Thread by Christopher Benson-Manica |
last post: by
|
2 posts
views
Thread by pei_world |
last post: by
|
4 posts
views
Thread by Frederik Vanderhaegen |
last post: by
|
1 post
views
Thread by tony |
last post: by
|
4 posts
views
Thread by fireball |
last post: by
|
1 post
views
Thread by Zeljko Bilandzija |
last post: by
| | | | | | | | | | |