Composite class problem

L

Le Géant Vert

Dave said:
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 composition.
Unfortunately, CMeshLoader sometimes needs to refer
to private members of C3DEngine. Inheritance, friends, and composition are
all swirling around in my head at the moment. I know that
inheritance is not the solution. Can someone please suggest an elegant way
of solving this problem?

Cheers
dave :)

in the class C3DEngine, what about just supplying getters to read the
private members, and matching setters to write them ?
anyway, a class using a second one which needs data from the first, doesn't
seem really right for me.... ? maybe you should wonder about the conception
and WHY does your mesh loader need data from the engine, and maybe there's
some way to externalize or refactor parts of code to make it more intuitive.
 
C

Cy Edmunds

Dave said:
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 composition.
Unfortunately, CMeshLoader sometimes needs to refer
to private members of C3DEngine. Inheritance, friends, and composition are
all swirling around in my head at the moment. I know that
inheritance is not the solution. Can someone please suggest an elegant way
of solving this problem?

Cheers
dave :)

Dave-

I have to agree with the Jolly Green Giant (Le Geant Vert) on this one.
Partitioning the program into input, processing, and output was how we wrote
Fortran programs back in the '60's. With object oriented programming an
object should take care of its own initialization. In your case this
indicates that C3DEngine should have a method, not a separate class, for
reading the input data. If you need a plugin to deal with different data
formats you can try templates or polymorphism. You might want to wade
through the Design Patterns book for ideas. Good luck.
 
C

Chris Theis

Le Géant Vert said:
[SNIP] >
in the class C3DEngine, what about just supplying getters to read the
private members, and matching setters to write them ?
anyway, a class using a second one which needs data from the first, doesn't
seem really right for me.... ? maybe you should wonder about the conception
and WHY does your mesh loader need data from the engine, and maybe there's
some way to externalize or refactor parts of code to make it more intuitive.

Well, there are certainly cases when it is absolutely fine that a
class/object that is included in a first one needs data from that. Imagine
for example a CUniverse class the encloses a CPlanet object. It's absolutely
fine that for example that CPlanet object obtains the current time from
CUniverse during the simulation of a 3 body problem. In principle I also
think that supplying access functions is the best idea.

Regards
Chris
 
L

Le Géant Vert

Chris Theis said:
Le Géant Vert said:
[SNIP] >
in the class C3DEngine, what about just supplying getters to read the
private members, and matching setters to write them ?
anyway, a class using a second one which needs data from the first, doesn't
seem really right for me.... ? maybe you should wonder about the conception
and WHY does your mesh loader need data from the engine, and maybe there's
some way to externalize or refactor parts of code to make it more intuitive.

Well, there are certainly cases when it is absolutely fine that a
class/object that is included in a first one needs data from that. Imagine
for example a CUniverse class the encloses a CPlanet object. It's absolutely
fine that for example that CPlanet object obtains the current time from
CUniverse during the simulation of a 3 body problem. In principle I also
think that supplying access functions is the best idea.

Regards
Chris

yep, there's always a lot of solutions to a single problem, nevertheless, I
usually have the feeling that when I have a "dual dependancy" (a class
containing another using, the last requiring data from the first), there
must be some way to improve the code design ; without criticizing, this is
my point of view. For example, with your CUniverse and CPlanet, maybe I'll
had some kinda "synchronize()" method to the CUniverse in order to dispath
the time information to all the planets, if the problem allows it. This may
have exactly the same results depending on the context, but this way, the
information are going from the top the bottom of the hierarchy without
needing "dual exchanges".
but of course, I'm pretty sure we can easily find examples where we do have
to go the way you're explaining :)
 
D

David White

Le Géant Vert said:
in the class C3DEngine, what about just supplying getters to read the
private members, and matching setters to write them ?

That defeats the purpose of making them private, and IMO isn't any improvement on reading and
writing the private members directly.

I don't see anything wrong with having one class accessing another's private members as a friend
as long as the accessing class is considered to 'belong' to the class it's accessing. Think of
the two classes as a pair that go together.

However, I'm not sure about the C3DEngine having a CMeshLoader as a member object. File loading
doesn't sound like an inherent responsibility of C3DEngine, which I assume is there to do 3D
stuff. If so, I'd rather separate file loading from it entirely by having the owner of the
C3DEngine create the CMeshLoader object to initialize the C3DEngine as necessary.

DW
 
D

Dave

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 composition.
Unfortunately, CMeshLoader sometimes needs to refer
to private members of C3DEngine. Inheritance, friends, and composition are
all swirling around in my head at the moment. I know that
inheritance is not the solution. Can someone please suggest an elegant way
of solving this problem?

Cheers
dave :)
 
C

Chris \( Val \)

[snip]

| in the class C3DEngine, what about just supplying getters to read the
| private members, and matching setters to write them ?

| anyway, a class using a second one which needs data from the first, doesn't
| seem really right for me.... ? maybe you should wonder about the conception
| and WHY does your mesh loader need data from the engine, and maybe there's
| some way to externalize or refactor parts of code to make it more intuitive.

Composition can sometimes be a better choice than inheritence
though. In the following example, a 'Car' is represented as a
composite class, rather than an inheritence heirarchy.

class Car
{
Engine E;
Transmission T;
public:
Car( const Engine& e, const Transmission& t )
: E( e ), T( t ) {}
};

An 'Engine' is not a 'Car', nor is a 'Transmission', so the
inheritence model doesn't realy make much sense. However,
a 'Car' *Has-A* engine and *Has-A* transmission, and this
is where composition can help.

I admit, that composition can get complex real quickly when
you need to manage communication between your objects :), but
there are times where it can better model a real world object
imo.

Cheers.
Chris Val
 
R

Rolf Magnus

David said:
That defeats the purpose of making them private, and IMO isn't any
improvement on reading and writing the private members directly.

It is an improvement. If you decide for some reason that the
implementation should be changed, you can still do that without
changing the interface. That's the point of making things private.
I don't see anything wrong with having one class accessing another's
private members as a friend as long as the accessing class is
considered to 'belong' to the class it's accessing. Think of the two
classes as a pair that go together.

I agree.
 
L

Le Géant Vert

David White said:
That defeats the purpose of making them private, and IMO isn't any improvement on reading and
writing the private members directly.

I don't see anything wrong with having one class accessing another's private members as a friend
as long as the accessing class is considered to 'belong' to the class it's accessing. Think of
the two classes as a pair that go together.

However, I'm not sure about the C3DEngine having a CMeshLoader as a member object. File loading
doesn't sound like an inherent responsibility of C3DEngine, which I assume is there to do 3D
stuff. If so, I'd rather separate file loading from it entirely by having the owner of the
C3DEngine create the CMeshLoader object to initialize the C3DEngine as necessary.

DW

same as Rolf.

anyway, if a class is "belonging" to another one, and those two should be
considered as a pair that go together, maybe making an inner-class could
clarify this strong relationship. Thus, as your pointing, the CMeshLoader
shouldn't be aggregated to the C3DEnging.

Maybe I'd make the CMeshLoader a singleton, filling one or more
CMeshLibrary, this lately being used by the C3DEngine... :-?
If we knew WHY the meshloader needs data from the 3D engine, we should
certainly be able to find more appropriate class design...
 
L

Le Géant Vert

Chris ( Val ) said:
[snip]

| in the class C3DEngine, what about just supplying getters to read the
| private members, and matching setters to write them ?

| anyway, a class using a second one which needs data from the first, doesn't
| seem really right for me.... ? maybe you should wonder about the conception
| and WHY does your mesh loader need data from the engine, and maybe there's
| some way to externalize or refactor parts of code to make it more intuitive.

Composition can sometimes be a better choice than inheritence
though. In the following example, a 'Car' is represented as a
composite class, rather than an inheritence heirarchy.

I've never said that inheritence should be prefered to composition (in fact,
I'm thinking almost the opposite, too much inheritence leads to complex
class design that can't be modified easiky when changes or evolutions are
needed... huge inheritence hierachy makes refactoring harder in general, I
think)
What I'm saying is that when composition is used, "dual depency" (A uses a
B, but B needs data from A ....) sounds weird to me... and design should be
reviewed, when possible.

anyway, thx for the "composition howto" :)
 
D

Dan W.

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 composition.

I've been working on a 3D engine myself, on and off for the past 2 yr.
Unfortunately, CMeshLoader sometimes needs to refer
to private members of C3DEngine. Inheritance, friends, and composition are
all swirling around in my head at the moment. I know that
inheritance is not the solution. Can someone please suggest an elegant way
of solving this problem?

I banged my head on the wall over the same thing. Tons of
environmental stuff that you'd think should be members of the
'TopClass'. That's where the whole misconception lies.

You just need a few server classes; some could be singletons, some
not.

You'll probably need a class to represent the camera.
Initially camera could be a singleton; but eventually you'll have a
vector of cameras, as you'll need extra ones for mirror reflections,
etc.

The World class: It doesn't matter that the world 'contains' all
things, in the real world. In the programming world, World is just a
data server.

Camera, World, App, OGLobj, Lighting, these are all classes that have
tons of data members, are seldom modified (once per frame), but are
accessed very often. Tons of get functions to write.

There's no need to put 'stuff' inside World; try NOT to put things
inside other things unless there's a practical reason to. Otherwise
you'll end up having to write,

the_world->continent[2]->country[7]->city[3]...->my_cat->move()

if you know what I mean.
Google up on Extreme Programming, and make it as simple as possible.

Cheers!
 
D

David White

Le Géant Vert said:
same as Rolf.

anyway, if a class is "belonging" to another one, and those two should be
considered as a pair that go together, maybe making an inner-class could
clarify this strong relationship.

For maintenance purposes, they need to be considered a pair, because if one changes the other
will probably need to change as well. However, in another way I'd prefer them to be completely
separate from each other. If C3DEngine is primarily doing 3D stuff, and if it's reasonably
general-purpose, then it's conceivable that some applications would not need the CMeshLoader,
and wouldn't want to have to even compile it. So, I'd want to keep them apart, but at the same
time not forget that if C3DEngine changes - including even its private members - then
CMeshLoader has to change also. I'm not sure how best to achieve both.
Thus, as your pointing, the CMeshLoader
shouldn't be aggregated to the C3DEnging.

Maybe I'd make the CMeshLoader a singleton, filling one or more
CMeshLibrary, this lately being used by the C3DEngine... :-?
If we knew WHY the meshloader needs data from the 3D engine, we should
certainly be able to find more appropriate class design...

My understanding is that CMeshLoader loads the values of C3DEngine's data members and then
assigns those members to the loaded values, so CMeshLoader is a sort of serialization class.

DW
 
D

David White

Le Géant Vert said:
I've never said that inheritence should be prefered to composition (in fact,
I'm thinking almost the opposite, too much inheritence leads to complex
class design that can't be modified easiky when changes or evolutions are
needed... huge inheritence hierachy makes refactoring harder in general, I
think)

Not only that, but wherever you have one object interacting with another, you have an
opportunity to make use of polymorphism. If you use a mixture of inheritance and composition,
then the combination of many objects interacting, where each object can be one of several
different classes, can give an application enormous flexibility in its run-time behaviour.

DW
 
C

Chris \( Val \)

|
| "Chris ( Val )" <[email protected]> a écrit dans le message de | [email protected]...

[snip]

| > Composition can sometimes be a better choice than inheritence
| > though. In the following example, a 'Car' is represented as a
| > composite class, rather than an inheritence heirarchy.
| >
|
| I've never said that inheritence should be prefered to composition (in fact,
| I'm thinking almost the opposite, too much inheritence leads to complex

My apologies - I didn't mean to imply that you did
prefer one over the other. It is difficult to get
ones point across, in a textual manner sometimes :).

| class design that can't be modified easiky when changes or evolutions are
| needed... huge inheritence hierachy makes refactoring harder in general, I
| think)
| What I'm saying is that when composition is used, "dual depency" (A uses a
| B, but B needs data from A ....) sounds weird to me... and design should be
| reviewed, when possible.

Agreed.

| anyway, thx for the "composition howto" :)

Any time :).

Cheers.
Chris Val
 
C

Chris \( Val \)

| hmmm well in lieu of major reconstruction, i think at the moment
| my best solution is to simply pass a pointer of C3DEngine to CMeshLoader.
| Not
| to flash, but does the job. Thanks all for your help, its most appreciated.

Hi Dave.

Since we haven't seen any of your code, it is difficult to
explain away some kind of sample - but since I like samples :),
here is one that uses member functions to pass the 3DEngine
object around via reference.

It is a *wild rough guess*, but it should present some ideas:

# include <iostream>
# include <fstream>
# include <ostream>

class C3DEngine;

class CMeshLoader
{
private:
std::ifstream InFile;
public:
template<class T>
bool LoadData( const std::string& Filename, const T& Engine )
{
if( Engine.IsReady() ) // Attempt to load data file...
{
InFile.open( Filename.c_str() );

if( !InFile )
return false;
else
return true;
}

return false;
}
};

class C3DEngine
{
private:
std::string FileName;
bool EngineReady;
CMeshLoader Loader;
public:
C3DEngine( const std::string& filename, const bool& state = false )
: FileName( filename ), EngineReady( state ) {}

bool LoadData() { return Loader.LoadData( FileName, *this ); }
bool IsReady() const { return EngineReady; }
};

int main()
{
C3DEngine Engine( "DataFile.txt", true );

if( Engine.LoadData() )
std::cout << "Engine data loaded. " << std::endl;
else
std::cout << "ERROR: Could not load up engine. "
<< std::endl;

return 0;
}

Cheers.
Chris Val
 
D

Dave

hmmm well in lieu of major reconstruction, i think at the moment
my best solution is to simply pass a pointer of C3DEngine to CMeshLoader.
Not
to flash, but does the job. Thanks all for your help, its most appreciated.

cheers
dave
 

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
474,155
Messages
2,570,871
Members
47,401
Latest member
CliffGrime

Latest Threads

Top