 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Dirk Gregorius Guest
|
Posted: Mon Sep 27, 2004 9:14 pm Post subject: Public data members |
|
|
Hi,
I have a class that is a simple wrapper around two STL container.
Basically it is something like this:
class Object
{
public:
// Some full flavor interface acually only repeating
// the functionalit of the container classes
private:
std::map<std::string, std::string> m_Dico;
std::vector<int> m_Numbers;
};
This class has no invariant, so I am wondering if I can make both data
members public and access them directly. You always read that this
break encapsulation, but on the other hand I had to repeat a lot of
functionality. In the calling code I need to to search, sort and
iterate over both containers, so in the above code I need to write
code like GetVectorBegin(), GetMapBegin(), FindInMap() and delegate
everything to the container classes. Since this doesn't raise the
abstraction and since I don't need to defend any invariant I am
wondering if simply defining a struct (s. below) would be the better
choice?
struct
{
std::map<std::string, std::string> m_Dico;
std::vector<int> m_Numbers;
};
Questions:
What are the current opinions and recommendations on public data
members - maybe taking into consideration the later use the STL
algorithms?
How should I declare the class interface of the first example in order
to make it STL algorithms compatible?
How about the use of typedefs?
Best regards,
Dirk
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Thorsten Ottosen Guest
|
Posted: Tue Sep 28, 2004 10:20 am Post subject: Re: Public data members |
|
|
"Dirk Gregorius" <dirk (AT) dirkgregorius (DOT) de> wrote
| Quote: | Hi,
I have a class that is a simple wrapper around two STL container.
Basically it is something like this:
class Object
{
public:
// Some full flavor interface acually only repeating
// the functionalit of the container classes
private:
std::map<std::string, std::string> m_Dico;
std::vector<int> m_Numbers;
};
This class has no invariant, so I am wondering if I can make both data
members public and access them directly.
|
yes, if there is no invariant then there is nothing for member functions to
protect.
br
Thorsten
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ulrich Eckhardt Guest
|
Posted: Tue Sep 28, 2004 10:38 am Post subject: Re: Public data members |
|
|
Dirk Gregorius wrote:
| Quote: | I have a class that is a simple wrapper around two STL container.
Basically it is something like this:
class Object
{
public:
// Some full flavor interface acually only repeating
// the functionalit of the container classes
private:
std::map<std::string, std::string> m_Dico;
std::vector<int> m_Numbers;
};
This class has no invariant, so I am wondering if I can make both data
members public and access them directly. You always read that this
break encapsulation, but on the other hand I had to repeat a lot of
functionality.
|
I would do it, but with a slight addition: add typedefs for the container
types. Also, I tend to remove the m_ from fublic members, but that is just
a matter of taste.
The point is, as you already figured out, your struct is just like one of
the std::containers - their elements are also unrestrictedly accessible.
Now I think about it, did you consider using std::pair<>? Anyhow, mere
aggregations of data that show no behaviour can usually be left in public.
hth
Uli
--
FAQ: http://parashift.com/c++-faq-lite/
/* bittersweet C++ */
default: break;
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
jakacki Guest
|
Posted: Tue Sep 28, 2004 10:40 am Post subject: Re: Public data members |
|
|
| Quote: | I have a class that is a simple wrapper around two STL
container. Basically it is something like this:
class Object
{
public:
// Some full flavor interface acually only repeating
// the functionalit of the container classes
private:
std::map<std::string, std::string> m_Dico;
std::vector<int> m_Numbers;
};
This class has no invariant,
|
Has trivial invariant ('true').
| Quote: | so I am wondering if I can make both data members public
and access them directly. You always read that this break
encapsulation, but on the other hand I had to repeat a
lot of functionality. In the calling code I need to to
search, sort and iterate over both containers, so in the
above code I need to write code like GetVectorBegin(),
GetMapBegin(), FindInMap() and delegate everything to the
container classes. Since this doesn't raise the
abstraction and since I don't need to defend any
invariant I am wondering if simply defining a struct (s.
below) would be the better choice?
|
If they are really deprived of any domain specific
semantics, why do you keep them together in one
class/structure ?
| Quote: | struct
{
std::map<std::string, std::string> m_Dico;
std::vector<int> m_Numbers;
};
Questions:
What are the current opinions and recommendations on
public data members - maybe taking into consideration the
later use the STL algorithms?
|
Encapsulation will allow you at least to optimize the
data structure if, some time later you discover that
80% of map keys are shorter than 3. Also if a lot of
code is going to depend on your interface it is wise to
encapsulate early.
| Quote: | How should I declare the class interface of the first
example in order to make it STL algorithms compatible?
|
What is "STL algorithms compatible" ? Your class looks like
a container, STL algorithms do not work on containers, they
work on iterators. Just have your container provide
STL-compliant iterators.
| Quote: | How about the use of typedefs?
|
What use of typedefs?
BR
Grzegorz
--
Free C++ frontend library: http://opencxx.sourceforge.net
China from the inside: http://www.staryhutong.com
Myself: http://www.dziupla.net/gj/cv
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Tue Sep 28, 2004 9:23 pm Post subject: Re: Public data members |
|
|
[email]dirk (AT) dirkgregorius (DOT) de[/email] (Dirk Gregorius) wrote in message
news:<d5c0fb78.0409271113.3fd36af3 (AT) posting (DOT) google.com>...
| Quote: | I have a class that is a simple wrapper around two STL container.
Basically it is something like this:
class Object
{
public:
// Some full flavor interface acually only repeating
// the functionalit of the container classes
private:
std::map<std::string, std::string> m_Dico;
std::vector<int> m_Numbers;
};
This class has no invariant, so I am wondering if I can make both data
members public and access them directly.
|
I do it. There are still cases where a good old C struct is what is
called for.
| Quote: | You always read that this break encapsulation, but on the other hand I
had to repeat a lot of functionality.
|
The question is: what are you encapsulating. Typically, either all data
members will be private, or all data members will be public, and there
will be no member functions (except maybe some convenience
constructors -- or, in one very special case, a conversion operator).
--
James Kanze GABI Software http://www.gabi-soft.fr
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
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Dirk Gregorius Guest
|
Posted: Wed Sep 29, 2004 9:41 am Post subject: Re: Public data members |
|
|
| Quote: | I would do it, but with a slight addition: add typedefs for the container
types. Also, I tend to remove the m_ from fublic members, but that is just
a matter of taste.
That's what I meant with typedef and I think this is the way I will |
go.
| Quote: | What is "STL algorithms compatible" ? Your class looks like
a container, STL algorithms do not work on containers, the
work on iterators. Just have your container provide
STL-compliant iterators.
Is there a standard way to do this? This comes to my head: |
class Object
{
public:
typedef std::map<std::string, std::string>::iterator MapIterator;
typedef std::vector<int>::iterator VectorIterator;
MapIterator MapBegin( void ); // Delegate to the map
VectorIterator VectorBegin( void ); // Delegate to the vector
// ...
private:
std::map<std::string, std::string> m_Map;
std::vector<int> m_Vector;
};
I need this class to load data from a file. The data is a list of
entities where each entity consists of pairs of strings and optional
some geometric data.
First I implemented a full flavour class whith rich interfaces and
everything possible I could imagine. Then my opinion changed I
implemented a simple function that loads the data simply into a
std::vector<>, which is actually what the file does. Most when not all
of the processing will be standard algortihms, so at the moment I
think that getting rid of all the unneeded indirections is better. On
the other hand I am not the experienced programmer in the world and in
all the books you read always this Dos and Donts and one of them is:
No public data memebers. For this low level objects I though it could
make sense to get rid of the indirections and asked here if this is
possible not a NoNo.
-Dirk
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Dave Harris Guest
|
Posted: Wed Sep 29, 2004 9:58 am Post subject: Re: Public data members |
|
|
[email]dirk (AT) dirkgregorius (DOT) de[/email] (Dirk Gregorius) wrote (abridged):
| Quote: | This class has no invariant, so I am wondering if I can make both data
members public and access them directly. You always read that this
break encapsulation, but on the other hand I had to repeat a lot of
functionality. In the calling code I need to to search, sort and
iterate over both containers, so in the above code I need to write
code like GetVectorBegin(), GetMapBegin(), FindInMap() and delegate
everything to the container classes.
|
I hope you could find better names that referred to their domain meaning
rather than their implementation. Eg numbers_begin() is better than
vector_begin(). This isn't just a cosmetic matter. Part of the job of a
class is to manage levels of abstraction.
| Quote: | What are the current opinions and recommendations on public data
members - maybe taking into consideration the later use the STL
algorithms?
|
In practice I find even the simplest classes evolve. I might change from
vector to map or list, or fixed-sized array, or I might need the data to
be sorted, or I might need to allocate it on first use, or whatever. I
also often find that code which uses the data is simpler and shorter if it
lives in the class which defines it. In other words, rather than:
for (Object::Numbers::iterator i = object.m_Numbers.begin();
i != object.m_Numbers.end(); ++i)
use( *i );
I will have:
void Object::use_all_numbers() {
for (Numbers::iterator i = numbers_begin(); i != numbers_end();
++i)
use( *i );
}
Doing this lessens the need to make lower level access public. Life is
even simpler if no class has to work on more than one collection, and it
can be worth making extra classes to achieve this:
void Numbers::use_all() {
for (iterator i = begin(); i != end(); ++i)
use( *i );
}
We no longer have to prefix everything with Object::Numbers::, so now the
loop fits on one 80-column line. This feels better engineered to me, even
if it means writing forwarding functions like:
void Object::use_all_numbers() {
m_numbers.use_all();
}
I don't much use STL algorithms. If I do use them they will probably be
hidden in the implementation of Object, rather than in client code. That
said, I often publish numbers_begin() and numbers_end(), which is all most
STL algorithms need.
The upshot is that I tend to make data private, use typedefs, and write
member functions which often just forward to the container or STL. I have
a lot of classes which have:
class MyContainer {
public:
typedef std::vector<int> Base;
typedef Base::const_iterator const_iterator;
typedef Base::iterator iterator;
bool empty() const;
int size() const;
const_iterator begin() const;
const_iterator end() const;
iterator begin();
iterator end();
private:
Base m_base;
};
inline bool MyContainer::empty() const {
return m_base.empty();
}
// etc
plus other members. On those occasions where I've made variables public
instead, because they were just "dumb data", I've usually ended up
reversing the decision and making the data smarter.
-- Dave Harris, Nottingham, UK
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Richard Guest
|
Posted: Thu Sep 30, 2004 10:46 am Post subject: Re: Public data members |
|
|
"jakacki" <jakacki_hates_spam (AT) acm (DOT) org> wrote
| Quote: | I have a class that is a simple wrapper around two STL
container. Basically it is something like this:
class Object
{
public:
// Some full flavor interface acually only repeating
// the functionalit of the container classes
private:
std::map<std::string, std::string> m_Dico;
std::vector<int> m_Numbers;
};
This class has no invariant,
Encapsulation will allow you at least to optimize the
data structure if, some time later you discover that
80% of map keys are shorter than 3. Also if a lot of
code is going to depend on your interface it is wise to
encapsulate early.
|
Why optimize something now that you don't know if you are going to use then.
I would just leave them public. Don't encapsulate for the sake of encapsulation.
/Richard
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Peter Schneider Guest
|
Posted: Fri Oct 01, 2004 4:13 pm Post subject: Re: Public data members |
|
|
Hi,
"Richard" <glanmark (AT) yahoo (DOT) com> wrote
| Quote: | "jakacki" <jakacki_hates_spam (AT) acm (DOT) org> wrote
|
[> > OP Dirk wrote]
| Quote: | I have a class that is a simple wrapper around two STL
container. Basically it is something like this:
class Object
{
public:
// Some full flavor interface acually only repeating
// the functionalit of the container classes
private:
std::map<std::string, std::string> m_Dico;
std::vector<int> m_Numbers;
};
This class has no invariant,
Encapsulation will allow you at least to optimize the
data structure if, some time later you discover that
80% of map keys are shorter than 3. Also if a lot of
code is going to depend on your interface it is wise to
encapsulate early.
Why optimize something now that you don't
know if you are going to use then.
|
But that's the whole point: Encapsulation preserves the
possibility to do yet unknown things
later, for yet unknown reasons,
by yet unknown programmers.
It's an investment. Bad investments can be costly;
missed investments are deadly.
Regards, Peter
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|