Pointer to member object operator

Started by
10 comments, last by ToohrVyk 16 years, 8 months ago
Currently I have a class like
class B;

class A {
public:
  B *bptr;
}
At certain times during my program bptr gets set to a new B. I then do things like B->myFunction(). Now I've implement the [] operator in B. All is okay upto here. Then I want to be able to do bptr....... but I don't think I can because bptr is a pointer to B not actually a B itself. I think I'd have to do bptr->??? Or something like that. How can I declare bptr so I can do things like bptr and it call my [] operator, which is what I want to do? TIA btw bptr used to be an array which is used extensively through my code as bptr[]. I want to replace the simple array with an object with the [] operator so I don't have to re-write my code.
Advertisement
I think the proper notation is (*bptr).
You could also do this:
B& b=*bptr;
b;
Quote:Original post by coordz
btw bptr used to be an array which is used extensively through my code as bptr[]. I want to replace the simple array with an object with the [] operator so I don't have to re-write my code.

C++ already has an object that behaves like an array, its called std::vector, it even overloads the [] operator and come with handy methods to determine the size of the array, whether its empty or not, to remove elements from anywhere in the array and all sorts really, so theres no need to write your own!
As with most things, its recommended to use the tools that come with the language.
Quote:Original post by dmatter
Quote:Original post by coordz
btw bptr used to be an array which is used extensively through my code as bptr[]. I want to replace the simple array with an object with the [] operator so I don't have to re-write my code.

C++ already has an object that behaves like an array, its called std::vector, it even overloads the [] operator and come with handy methods to determine the size of the array, whether its empty or not, to remove elements from anywhere in the array and all sorts really, so theres no need to write your own!
As with most things, its recommended to use the tools that come with the language.

Thanks dmatter but sadly std::array doesn't cut it. I'm actually implementing a wrapper for a sparse array (based on std::map) which includes some additional functionality. I don't understand the STL well enough to start modifying std::map so I'm wrapping it.

Depends on your intended usage. Your current approach is valid as long as:

  • B is a container class with a subscript operator defined (std::vector, std::map, std::deque or your own associative container).
  • An instance of class A may reference zero or one such containers, the reference must be re-seatable, the referenced container is not owned by the instance, and guaranteed to remain available for the lifetime of the instance.


As stevenmarky explained, the correct use case for this is (*this->bptr).

If, however, the referenced container is internal (as you seem to imply), then you can manipulate an instance instead of a pointer, either defining it as B b; and using it as this->b; instead (if you can equate the concepts of "no container" and "empty container") or defining it as boost::optional<B> b; and using it, again, as (*this->b);. As a last resort, you could use auto_ptr<B> b; to emulate the external behaviour of boost::optional, though you would need to write any copy constructors for A yourself.

Of course, other ownership conditions may call for boost::shared_ptr instead.

Quote:Original post by coordz
I'm actually implementing a wrapper for a sparse array (based on std::map) which includes some additional functionality. I don't understand the STL well enough to start modifying std::map so I'm wrapping it.

This is fine. If you werent adding extra functionality then you might as well use a std::map directly, probably using a typedef to hide the tedious template syntax.
You won't ever want to modify the STL container directly, aggregating them in another class in this way is the correct way to extend them, along with using/writing STL compliant algorithms.
Modifying or inheriting from STL containers is a definate NO.
Quote:Original post by dmatter
Quote:Original post by coordz
I'm actually implementing a wrapper for a sparse array (based on std::map) which includes some additional functionality. I don't understand the STL well enough to start modifying std::map so I'm wrapping it.

This is fine. If you werent adding extra functionality then you might as well use a std::map directly, probably using a typedef to hide the tedious template syntax.
You won't ever want to modify the STL container directly, aggregating them in another class in this way is the correct way to extend them, along with using/writing STL compliant algorithms.
Modifying or inheriting from STL containers is a definate NO.


What kind of "additional functionality", though?
Quote:Original post by Zahlman
What kind of "additional functionality", though?

Well to be honest I dont really know, off the top of my head I cant really think what you would want out of a one-dimensioned sparse array that you can't get from a vanilla std::map. Perhaps its as simple as implementing the adaptor pattern?

But in general, 'additional functionality' would just be anything that isnt provided by the std::map, whether that's in terms of the interface in the case of the adapter pattern or if you were adding some form 'higher level' functionality such as a multi-dimensional sparse array or building a resource manager perhaps.

Edit: I could possibly attempt to generalise this to "any class that provides a service whos implementation is based on an STL container should aggregate the container."
Quote:btw bptr used to be an array which is used extensively through my code as bptr[]. I want to replace the simple array with an object with the [] operator so I don't have to re-write my code.


When dealing with custom types and pointers, prefer to use typedefs. For example:
class B;class A {public:  typedef B * BPtr;  BPtr bptr;};...A a;A::BPtr p = a.bptr;// orclass B;typedef B * BPtr;class A {public:  BPtr bptr;};...A a;BPtr p = a.bptr;


But for your particular case:

class BPtr{public:  B &operator( size_t subscript )  {    return //get proper element from storage  }  // also override assignment operator, copy constructor, and everything else.private:  // storage}class A {public:private:  BPtr bptr;}


This should allow you to keep the same code elsewhere.
Quote:Original post by dmatter
Quote:Original post by Zahlman
What kind of "additional functionality", though?

Well to be honest I dont really know, off the top of my head I cant really think what you would want out of a one-dimensioned sparse array that you can't get from a vanilla std::map. Perhaps its as simple as implementing the adaptor pattern?

But in general, 'additional functionality' would just be anything that isnt provided by the std::map, whether that's in terms of the interface in the case of the adapter pattern or if you were adding some form 'higher level' functionality such as a multi-dimensional sparse array or building a resource manager perhaps.

Edit: I could possibly attempt to generalise this to "any class that provides a service whos implementation is based on an STL container should aggregate the container."


Hehe. I'll wait for the OP's answer ;) But what I'm getting at is that this functionality might be better implemented at the containing-class level instead.

This topic is closed to new replies.

Advertisement