Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Handle class and dereferencing operator

Posted on 2014-01-13
5
Medium Priority
?
418 Views
Last Modified: 2014-01-13
I have the following Handle (smart pointer) class, written as an exercise.

template <class T> class Handle
{
public:
	Handle() : p(0) { }
	Handle(T* t) : p(t)	{ }
	// copy constructor
	Handle(const Handle& h) : p(0)
	{
		if (h.p) // check if the handle points to something, otherwise there is nothing to clone
			p = h.p->clone();  // T must have a clone() method.
	}
	Handle& operator=(const Handle&); // assignment operator
	~Handle() { delete p; }
	// need to use comparison with NULL in order to avoid warning in VS 2010 and above
	operator bool() const { return (p != NULL); } // conversion operator from Handle to bool. Uses implicit conversion from pointer to bool
	T& operator*() const;
	T* operator->() const;
private:
	T* p;
};

Open in new window

The class appears to work perfectly fine. However, I have noticed that some books suggest that the * and -> operators should be overloaded in both const and non-const versions, e.g.

T& operator*();
const T& operator*() const

Open in new window

What is the advantage of doing that (if any)?
0
Comment
Question by:Rothbard
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
5 Comments
 
LVL 35

Expert Comment

by:sarabande
ID: 39776618
if using the following function

int f(Handle<int> & hx, const Handle<int> &hcx)
{
      int &  x = *hx;  
      const int &  cx = *hcx;  

      return 1111 + cx + x;
}

Open in new window


the first dereference expression would use the T& operator* while the second would use the const T& operator*. if both have the same implementation, it makes no difference, but you could use a different implementation, for example return a reference to a const static member if the pointer is 0 in the const operator while you throw an exception in the non-const operator.

Sara
0
 

Author Comment

by:Rothbard
ID: 39776645
Thanks for your comment. In my Handle class above, the * operator is implemented as follows

template <class T> T& Handle<T>::operator*() const
{
	if (p)
		return *p;
	else
		throw runtime_error("Attempting to dereference unbound Handle.");
}

Open in new window

I can see that your code for the f function runs fine with my definition of *, so I am still not sure why two separate versions are needed. The fact that the method operator*() is const allows it to work on const Handle objects, but it works equally well with non-const objects.
0
 
LVL 35

Assisted Solution

by:sarabande
sarabande earned 400 total points
ID: 39776679
I used the following implementation:

T& operator*()  
 { 
      return *p; 
 }
 const T& operator*() const 
 { 
      return *p; 
 }

Open in new window


and could see that the compiler used a different operator depending on the constness of the variables and arguments. because of that you could have a different implementation for read-only operations what might be useful sometimes.

Sara
0
 
LVL 40

Accepted Solution

by:
evilrix earned 1000 total points
ID: 39776774
It's only necessary to implement a const operator. There is no need to implement a non-const operator because constness of the smart pointer container does not reflect constness of the pointer it is managing.

The C++11 standard shared pointer only implements const operators, both return pointers to type T. T will define what the characteristics are of the pointer being managed. In other words T may or may not be const.

http://en.cppreference.com/w/cpp/memory/shared_ptr/operator*
0
 

Author Closing Comment

by:Rothbard
ID: 39776876
Thanks!
0

Featured Post

On Demand Webinar - Networking for the Cloud Era

This webinar discusses:
-Common barriers companies experience when moving to the cloud
-How SD-WAN changes the way we look at networks
-Best practices customers should employ moving forward with cloud migration
-What happens behind the scenes of SteelConnect’s one-click button

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
In days of old, returning something by value from a function in C++ was necessarily avoided because it would, invariably, involve one or even two copies of the object being created and potentially costly calls to a copy-constructor and destructor. A…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

722 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question