Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

Handle class and dereferencing operator

Posted on 2014-01-13
5
Medium Priority
?
422 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
  • 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

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

Question has a verified solution.

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

Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

885 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