How to do this better?

  • Thread starter Robert William Vesterman
  • Start date
R

Robert William Vesterman

I have a class that wants to keep track of all instances of itself.
So, I'm currently doing something like this:

class X
{
public:
X ( int blah );
const int blah();
~X();

private:
X();
X ( const X& rhs );
const X& operator= ( const X& rhs );
static vector<X *> *xList;
int blah_;
};

The private constructors and the operator= are not defined, so the
only way to make one is via the public constructor (right?).

The xList pointer is initially zero.

Whenever one of these is created, the constructor checks whether the
xList pointer is still zero, and if so, initializes it to a new
vector<X *>. It then pushes "this" onto xList..

Whenever one is destroyed, the destructor finds "this" on xList, and
erases it; if xList is then empty, it also does a delete on xList, and
sets xList back to zero.

So, my first question: Is there anything explicitly wrong with the
above?

Second: If nothing's outright wrong with it, is there a better way to
do it?

Now, the next thing is that I want the outside world to be able to
look at the list of existing x's - but not modify it. So, I defined a
couple of public static functions:

const vector<X *>::size_type getXCount();
const X& getX ( vector<X *>::size_type index );

If xList is zero, getXCount returns zero, else it returns
xList->size(). getX gives a const reference to the X at the desired
index (initializing xList first if it is zero) by using xList->at().
So it's going to throw some exception if an invalid index is
specified.

Third question: Anything wrong with that?

Fourth question: Is there a better way?

Really what I would like is to just let the outside world use standard
vector stuff to look through the list, but I do not want them to be
able to modify the list. So, for example, I would like them to be
able to begin(), find(), operator++, and so forth, but not
push_back(), erase(), and so forth. I could define all of these
functions statically in my X class, but is there a less verbose way?
Like (I don't know what I'm talking about here) a public function that
returns a const reference to the vector, or something?

Thanks in advance for any help.

Bob Vesterman.
 
V

Victor Bazarov

Robert William Vesterman said:
I have a class that wants to keep track of all instances of itself.
So, I'm currently doing something like this:

class X
{
public:
X ( int blah );
const int blah();
~X();

private:
X();
X ( const X& rhs );
const X& operator= ( const X& rhs );
static vector<X *> *xList;

I would use 'list' or 'set'. And there is no need to have it
as a pointer. Would eliminate the need to check it.
int blah_;
};

The private constructors and the operator= are not defined, so the
only way to make one is via the public constructor (right?).

The xList pointer is initially zero.

Whenever one of these is created, the constructor checks whether the
xList pointer is still zero, and if so, initializes it to a new
vector<X *>. It then pushes "this" onto xList..


If you don't declare it a pointer, there is no need to check,
just push.
Whenever one is destroyed, the destructor finds "this" on xList, and
erases it; if xList is then empty, it also does a delete on xList, and
sets xList back to zero.

So, my first question: Is there anything explicitly wrong with the
above?
No.


Second: If nothing's outright wrong with it, is there a better way to
do it?

Use 'list' or 'set'. They are faster WRT insertions/deletions
than a 'vector'.
Now, the next thing is that I want the outside world to be able to
look at the list of existing x's - but not modify it. So, I defined a
couple of public static functions:

const vector<X *>::size_type getXCount();
const X& getX ( vector<X *>::size_type index );

Both those members should probably be either static or const.
If xList is zero, getXCount returns zero, else it returns
xList->size(). getX gives a const reference to the X at the desired
index (initializing xList first if it is zero) by using xList->at().

If you define it as 'list', the order is preserved (just like in
a vector, but getting one from a particular index could be slower.
With a 'set' the creation (insertion) order is not preserved, and
getting one from a particular index is slow too. So, pick the
collection based on your requirements.
So it's going to throw some exception if an invalid index is
specified.

Third question: Anything wrong with that?

If the order is important, forget I suggested 'set'.
Fourth question: Is there a better way?

Naming or keeping an ID could be the next step. Then you might
want to look at 'map' as your container.
Really what I would like is to just let the outside world use standard
vector stuff to look through the list, but I do not want them to be
able to modify the list. So, for example, I would like them to be
able to begin(), find(), operator++, and so forth, but not
push_back(), erase(), and so forth. I could define all of these
functions statically in my X class, but is there a less verbose way?
Like (I don't know what I'm talking about here) a public function that
returns a const reference to the vector, or something?

Sure, you could do that.

operator const vector<X*> () const { return xList; }

(again, I don't think there is a need to have 'xList' as a pointer)

Victor
 
R

Robert William Vesterman

Sure, you could do that.

operator const vector<X*> () const { return xList; }

I am confused by this syntax. Could you please show how a client
class would use this to get the xList from X?

Also, am I correct in the following? The reason why the above would
not allow them to do (for example) a push_back() is because the vector
they're given is const, and push_back() is not a const function, and
is therefore not allowed on const objects?

Thanks,

Bob Vesterman.
 
V

Victor Bazarov

Robert William Vesterman said:
I am confused by this syntax. Could you please show how a client
class would use this to get the xList from X?

Also, am I correct in the following? The reason why the above would
not allow them to do (for example) a push_back() is because the vector
they're given is const, and push_back() is not a const function, and
is therefore not allowed on const objects?

First, let me say that I made a mistake. I intended to write

operator const vector<X*>& () const { return xList; }

because there is no need to copy the stuff, returning a reference
should be satisfactory.

As to how to use it, this should be an illustration:

const vector<X*>& v(yourClassInstance);

and then do what they want, like accessing v or v.begin()
or whatever. And yes, you're correct, since the vector is const
they won't be able to modify it directly (without a const_cast).

Victor
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top