[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

Design issue - Container as a member of a class

Stephen Howe

12/10/2008 11:16:00 PM

Hi

I know about public and private inheritance. And they do not seem
right here.

I frequently find that I have a container as a member of a class and I
wish to iterate over it. Yet the member is private (as data, it should
be). Exactly what should I be doing so that there should be an
interface?

Thanks

Stephen Howe
10 Answers

Jeff Schwab

12/10/2008 11:19:00 PM

0

Stephen Howe wrote:

> I know about public and private inheritance. And they do not seem
> right here.
>
> I frequently find that I have a container as a member of a class and I
> wish to iterate over it. Yet the member is private (as data, it should
> be). Exactly what should I be doing so that there should be an
> interface?

It's hard to tell, from this description, what high-level goal you're
trying to achieve. Rather than thinking of a class "exposing" its
internals, it may be better to consider what service the class is
providing, and to provide a member (or friend) function to serve that
purpose.

Victor Bazarov

12/10/2008 11:24:00 PM

0

Stephen Howe wrote:
> I know about public and private inheritance. And they do not seem
> right here.
>
> I frequently find that I have a container as a member of a class and I
> wish to iterate over it. Yet the member is private (as data, it should
> be). Exactly what should I be doing so that there should be an
> interface?

How would you like to "iterate"? You can write your own "for_each", you
can write an interface that exposes the "begin" and "end" of your
container, you can implement your own "start", "next", and "stop", along
with "reset" or some such. You can even perform indexing yourself (if
you think that your class should allow that, if it fits your model).

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

Daniel T.

12/11/2008 2:52:00 AM

0

Stephen Howe <sjhoweATdialDOTpipexDOTcom> wrote:

> I know about public and private inheritance. And they do not seem
> right here.
>
> I frequently find that I have a container as a member of a class and I
> wish to iterate over it. Yet the member is private (as data, it should
> be). Exactly what should I be doing so that there should be an
> interface?

Without more information, I agree with Jeff Schwab. Provide a member
function that users of the class can call to do whatever it is you want
to the things in the container.

Juha Nieminen

12/11/2008 2:22:00 PM

0

Stephen Howe wrote:
> I frequently find that I have a container as a member of a class and I
> wish to iterate over it.

From outside the class, you mean?

Then why not provide some suitable iterator, as well as a begin() and
end() function (might be also named otherwise, depending on the case) in
the public interface of your class? (The iterator might by as simple as
a typedef to the member container iterator.)

Stephen Howe

12/11/2008 4:50:00 PM

0

>It's hard to tell, from this description, what high-level goal you're
>trying to achieve. Rather than thinking of a class "exposing" its
>internals, it may be better to consider what service the class is
>providing, and to provide a member (or friend) function to serve that
>purpose.

Thanks all for the responses.

Most of my classes are like that. But just occasionally I find that I
have 2 classes that need to interrelate - and then I am stuck.
Perhaps the friend function is the answer.

In terms of concepts, I have many "panels" and within each panel, I
have "channels". "channels" being "Discovery", "Sky One", "Fox News"
etc.

I have one class that fetches data from a database with Panel'IDs and
Channel'IDs within that (all integral types).

But I also have a class which represents Secondary (or Virtual)
Panels. And this class tells me what Panels to look for in a days
worth of data, and if present, make a copy renaming the panel and
merging the data back into original container within the 1st class.

So effectively 1st class needs access to 2nd classes members.
The "services" the 2nd class is providing is more than just simple
inspector functions or you call a Mutator function and the internals
of the class are rearranged.

In this case the 1st class is changed having used large chuncks of the
2nd classes state.

I find this problem occurs a lot.
I am a used to Inspector and Mutator functions within a class.
But just occasionally one class is changed significantly needing
significant access to the other classes state.
Perhaps friendship is the answer.

Does that help or shoudl I show more.

Cheers

Stephen Howe

ram

12/11/2008 5:22:00 PM

0

Stephen Howe <sjhoweATdialDOTpipexDOTcom> writes:
>have 2 classes that need to interrelate - and then I am stuck.

All private information of an object I call the »kernel«, this
does not only include private fields but also any other
information a client should not know.

A function accessing the kernel of a object I call a »core
function of this object«.

Sometimes, a function needs to be a core function of two
objects. For example, there might be two device drivers for
storage media. Clients should not know the details of any of
the two media.

A fast copy function to copy from one medium two another
might need to be in the core of both objects, however.

In languages with classes, the core methods of an object
all go into the class of this object. But there is no place
for core methods of multiple objects.

In Java, in this case one is really lost (the only hack is
to declare all fields »public«). In C++, at least we have
friends. In CLOS, one might use multimethods.

Object-oriented programming is not the same as programming
with classes. C++ is C with classes. Classes follow the
idea to place each method into a single class. So they
introduce some limits. But surely, »friend« can help a lot.

In a hypothetical language, kernels and methods would not
have a 1:n, but an n:m relationship. E.g.:

kernel complex
{ private: double real; double imag; }

kernel device
{ private: DHANDLE handle; }

class complex, device
{ write()
{ /* writes complex value to a device */
/* can access private fields of both kernels */ }}

class complex
{ add( complex other )
{ /* adds two complex numbers */
/* can only access private fields of the kernel complex */ }}

Stephen Howe

12/11/2008 5:32:00 PM

0

>It's hard to tell, from this description, what high-level goal you're
>trying to achieve. Rather than thinking of a class "exposing" its
>internals, it may be better to consider what service the class is
>providing, and to provide a member (or friend) function to serve that
>purpose.

Hi

friendship looks a possible answer.
The only snag is that friend declaration seems

I would have

class LargeClass
{
// ...
};

class TinyClass
{

friend void LargeClass::SomeFunction();
};

just so that LargeClass::SomeFunction() can see the internals of
TinyClass. And this intrinsically feels incorrect, as it would mean
the header file for TinyClass would have to be aware of all other
classes to grant them friendship simply because of the difficulty of
abstracting away the guts of TinyClass in its interface.
You could grant the entire of LargeClass access to TinyClass but this
seems overkill.

Perhaps a free function that is friends of both is the answer?
Arguments passed by reference mean I dont have to have both classes
defined.

Cheers

Stephen Howe

Stephen Howe

12/11/2008 6:00:00 PM

0

On Wed, 10 Dec 2008 18:19:24 -0500, Jeff Schwab
<jeff@schwabcenter.com> wrote:

Iti s no bleat to those who have responded but I find that articles
that cover class design seem inadequate.

I know about public inheritance, the Liskov substitution principle.
I know about private inheritance meaning "implemented in terms of".

And I know about inheritance versus containment.
Opting for containment generates its own set of problems.

I know less about "mixins" and I am sure there are other design issues
that have escaped me. Are there any good books on this? Really I wish
to use the full gamut of what C++ offers and choose appropriately.

Thanks

Stephen Howe

James Kanze

12/12/2008 8:56:00 AM

0

On Dec 11, 3:22 pm, Juha Nieminen <nos...@thanks.invalid> wrote:
> Stephen Howe wrote:
> > I frequently find that I have a container as a member of a
> > class and I wish to iterate over it.

> From outside the class, you mean?

> Then why not provide some suitable iterator, as well as a
> begin() and end() function (might be also named otherwise,
> depending on the case) in the public interface of your class?
> (The iterator might by as simple as a typedef to the member
> container iterator.)

It the abstraction of the class is to contain a set of elements,
this rejoins what Jeff Schwab said: don't expose the container,
implement an interface which defines your abstraction.

In such cases, using a typedef to define the iterator will
expose something of your internal implementation; whether this
is a problem worth solving or not will depend on how widely used
the class is. Otherwise, it's pretty trivial to wrap an
iterator in another, in order to give it its own type (and
possibly making it appear as e.g. a forward iterator, even if
the underlying container happens to be a vector at present). If
the issue comes up often, it wouldn't be that difficult to write
a template class to handle it, in which case, a typedef to an
instantiation of the template would do the trick.

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Matthias Buelow

12/12/2008 3:09:00 PM

0

Stephen Howe wrote:

I frequently find that I have a container as a member of a class and I
> wish to iterate over it. Yet the member is private (as data, it should
> be). Exactly what should I be doing so that there should be an
> interface?

Expose an iterator, or just make the damn thing public. Privacy is
completely overrated in most cases (and often counter-productive) and
I'd only consider worrying about it if it's a library or module used
extensively by others. For program maintenance, it's much better to
abstract through types than by providing accessor functions, anyway.