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 2777
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 thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Dave |
last post by:
Hi
I'm making a 3D Engine which consists of the class C3DEngine. Part of this
engine is a file loader, a class called CMeshLoader.
I have made an instance of CMeshLoader in C3DEngine, ie...
|
by: fog |
last post by:
Given:
class A;
and B "has-a" A. The composition relationship between A and B can be
implemented in three ways:
===================
# 1.
class B
{
|
by: Florian G. Pflug |
last post by:
Hi
I installed a postgres-application (which was developed on debian
woody) on red hat 9 today, using the postgres 7.3 rpms from redhad.
One of my the triggers uses the pg_settings table (more...
|
by: Christopher Benson-Manica |
last post by:
Are these terms semantically identical? If so, which is to be
preferred when speaking of the construct they describe?
--
Christopher Benson-Manica | I *should* know what I'm talking about - if...
|
by: pei_world |
last post by:
can anyone help me with these problem, code written correctly except those
with * mark.
//==========================================================================
===============================...
|
by: Frederik Vanderhaegen |
last post by:
Hi,
Can anyone explain me the difference between aggregation and composition?
I know that they both are "whole-part" relationships and that composition
parts are destroyed when the composition...
|
by: tony |
last post by:
Hello!
I access the class MyComparer in this way.
steel_post.Sort(new MeltPracDataComposition.Composition.MyComparer());
You can see the class definition for MyComparer below.
As you can see...
|
by: fireball |
last post by:
hi, I got confused for a moment about creating data structure for UML
composition (strong aggregation) relation one-to-many.
I used Rose/DataModeler to do so.
<filled_diamond>--------
I...
|
by: Zeljko Bilandzija |
last post by:
Hello!
I have a problem, and I looking for help if someone can handle this.
I use asp.net 2.0, and I create web site which support users from internet
(Web Site Administration Tool) and with...
|
by: taylorcarr |
last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
|
by: Charles Arthur |
last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
|
by: ryjfgjl |
last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
|
by: ryjfgjl |
last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
|
by: BarryA |
last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
by: Hystou |
last post by:
There are some requirements for setting up RAID:
1. The motherboard and BIOS support RAID configuration.
2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers,...
| |