Consider this code
// Example program
#include <iostream>
#include <string>
class SmartPtr{
int *ptr;
public:
explicit SmartPtr(int *ptr=0){
ptr = new int;
}
~SmartPtr(){
std::cout<<"Dest is called"<<std::endl;}
int& operator *() //overloaded operator for dereferencing
{
std::cout<<"(*) is called .."<<std::endl;
return *ptr;
}
int * operator ->() //overloaded operator for referencing
{
std::cout<<"(*) is called .."<<std::endl;
return ptr;
}
};
int main()
{
SmartPtr p(new int());
*p = 20; //overloaded operator * called
std::cout<<*p<<std::endl; // Overloaded operator * called
// End of program
//Destructor called
}
here i have overloaded operators * and & , i want to understand why that type of function signature based on the comments i have mentioned in main function .
If someone can explain how it works ?
PS : I am new to C++ and explaination i am asking is trivial {i know :)}
This is the way smart pointers are constructed.
They are wrappers of pointers of any class and they control the deallocation of these objects by automatically calling their destructor when the smart pointer goes out of scope.
In order to expose the interface of the wrapped class, they must overload * and -> operators and return the wrapped object's pointer.
In C++ you can define functions as behavior of operators on your types. That is exactly, what happens here.
int& operator * () declares the function, that is used for the unary * operator. The result of that operator then is a reference to an int.
int* operator -> ()then declares the function for ->. This one is a bit special, since it will be used on the return value again, until there is a pointer, which will be used to apply the standard behavior of ->.
After you have declared these operators, the compiler will accept them on any object of your type. You can then write *myObj go get the result of the operator * () function.
This feature gives you the power to extend the language in parts. Note, that the return types can be chosen as needed. If you look at advanced libraries, that implement domain specific languages, you'll find a lot of that. Boost::spirit is an extreme example of that.
Related
Struct A
{
int* ptr;
int operator+=(const A& other)
{
// if(ptr == nullptr)
// { DoSomething(); }
// else { ...}
}
...
}
Is it possible to have a template operator+= (on a NON-template Class A) in order to resolve that if statement at compile time?
EDIT: I have a bunch of API's, all with the signature:
A funcX()
{
// lot of A's overloaded operators calls
return A;
}
Now, I need to use those API's with a new type, that shares a lot of members with A and add a new one (a smart pointer).
Since all the A funcX() return by value, I cannot derive my new type from A and call A funcX() with the derived type (slicing).
So my solution is to add a smart pointer to A, and a constructor in A that initializes that pointer.
So now I get to use all the API's, and when A is constructed with its new constructor (that initializes the pointer), I want all the operators to have a different behaviour than the existing one.
I was looking into some templates tricks to avoid the cost of checking the pointer inside each operator, although from the comments it doesn't seem possible to achieve it.
Suppose I have defined a class called Entity which has a data member which is a pointer to int. So for example
class Entity {
public:
int* ptr;
// other stuff
};
Is there a way to give the type int* a constructor which takes an Entity object? If I have an Entity object called my_entity, I'd like to be able to do something like this
int* p(my_entity);
or this
int* p = my_entity;
which would require the compiler implicitly call a constructor for int* that takes an Entity.
Is this possible? (I know I could define a public get_pointer() method in the Entity class and do something like int* p = my_entity.get_pointer(); but this seems clunky.)
Well, there is no constructor for a basic pointer - in the sense that there is no function implicitly called in order to initialise the pointer.
The closest you can come is to use a user-defined conversion operator function
class Entity
{
public:
operator int *();
};
Entity::operator int *()
{
// return something appropriate that is of type int *
}
// sample usage in a function somewhere
int *p = some_entity; // implicitly conversion that calls the operator int *()
int *another_p = static_cast<int *>(some_entity); // explicit conversion
int *yet_another_p = some_entity.operator int *();
There are variants of this, depending on what form of const qualification is needed (e.g. if the operator function doesn't change the object it acts on, it should be const and may be defined as operator const int *()).
It is necessary to ensure that the pointer returned by the operator function is treated appropriately. If the user defined operator function returns a member of some_entity, it cannot be used once some_entity ceases to exist. Similarly, if it uses dynamic memory allocation (e.g. return the result of a new expression) the caller must explicitly release that memory to avoid a memory leak.
You cant make a constructor for primitive types. Also there is no need to do this using constructor, you could just use a getter as you already mentioned, or a function to which you pass an Entity and int and store the int to Entity.
Also you can use a user-defined conversion as #Some programmer dude said and do something like:
int *p = (int*)my_entity;
noGiven a private Member pData
private:
T* pData; // Generic pointer to be stored
Below is the overloaded implementation of * and ->
T& operator* ()
{
return *pData;
}
T* operator-> ()
{
return pData;
}
We call the same from the main as shown below:
void main(){
SP<PERSON> p(new Person("Scott", 25));
p->Display();
}
I cannot understand how -> and "*" operator overloading will work here?
or to be more clear how p->Display(); will be interpreted?
The -> operator is special. When it returns an object, it is automatically applied again. If it returns another object it is also applied again, until finally a plain pointer is returned. This is called chaining, the plain pointer is finally dereferenced and the chain stops.
p->Display() is therefore interpreted like this:
p->Display(); // Compiler sees this
T* tmp = p.operator->(); // First applied operator-> (the one you provided)
tmp->Display(); // since T* is a pointer itself, operator-> (the built-in one for pointers) is applied
If I have a template class A which holds a pointer, and A has an implicit conversion operator which will return that pointer, do I need to, or should I, define a delete operator for A, if I intent to apply delete to objects of this class?
You only need to define operator delete if you define operator new -- in which case you pretty much must do so.
That doesn't mean that something won't need to delete your A*s -- but you don't need to define any operators for that, it will work by default.
I believe that you've got something like the following:
template <typename T>
struct A {
T * t;
operator T* () { return t; }
};
An you intend to "apply delete to objects of this class", so by that I'm assuming you mean:
void foo ()
{
A<int> * p = new A<int>;
delete p; // Applying 'delete'
}
If this is the case, then the call to delete correctly destroys the object and frees the the memory allocated by the use of 'new' on the previous line and the answer to your question is 'no'.
Because you have declared a conversion operator to a pointer, it is possible to use delete on an object of type A<int> (a opposed to A<int>*). The use of delete will be applied to the result of calling the conversion operator:
void foo ()
{
A<int> a;
a.t = new int;
delete a; // Same as: delete a.operator T*()
}
Basics of how delete works:
The expression delete p, does two different things. Firstly, it calls the destructor for the object pointed to by p and then it frees the memory. If you define an operator delete member for your class then it will be that function which will be used by delete p to free the memory.
In general, you only define those operators when you want to control how the memory for dynamic objects of that class should be allocated or freed.
If your class owns this pointer, it should delete it in its destructor. Be aware that overloading this operator may be confusing, because the usual approach to obtain a pointer to an object is by taking its address.
Does you class A really need to define an implicit conversion operator? Maybe have a simple T* get() const method that returns the pointer, like the boost and std smart pointer do. Implicit conversion can cause all kinds of trouble.
I know that you can use a dummy "int" parameter on operator++ and operator-- to override the postfix versions of those operators, but I vaguely recall something about a dummy parameter that you could declare on a destructor. Does anyone know anything about that, and if so, what that dummy parameter did?
This was in my old Turbo C++ tutorial books, which I read when I was a teenager (i.e. a long time ago), so I might be completely misremembering it. That was also very early C++, before it was standardized, so it's possible that it was something Turbo C++-specific.
You're possibly thinking of the placement and nothrow forms of operator delete, which have the signatures:
void operator delete(void *, void *) throw();
void operator delete(void *, const std::nothrow_t&) throw();
void operator delete[](void *, void *) throw();
void operator delete[](void *, const std::nothrow_t&) throw();
These are never called during normal operation, but would be used in the case where the constructor for an object being constructed with placement new throws an exception. Generally you don't have to define them, since the compiler already called the destructor(s) on the dead object's bases and members, and for placement new there's no memory to be freed. But can exist if you are overloading placement new and need a corresponding operator.
The second argument is not really used, and just distinguishes the signature for the ordinary:
void operator delete(void *)
These aren't special dummy arguments the way the operator++ ones are, though. They're just an instance of the general rule that call to new with extra arguments, such as:
obj = new(x,y,z) Object(a,b,c)
will generate implicit code to clean up from constructor errors that passes those same additional arguments to the operator delete, which will function (approximately) like:
void *raw = operator new(sizeof(Object), x,y,z)
try {
obj = new(raw) Object(a,b,c);
} catch(...) {
operator delete(raw,x,y,z);
throw;
}
Either you are misremembering, or you should try to forget it. Destructors don't have parameters, return types and they shouldn't throw exceptions.
I swear I've heard the same thing, but the C++ FAQ seems to say that there is no such form.
Perhaps you are thinking of placement new?
class MyClass { /* ... */ };
char * raw_mem = new char [sizeof (MyClass)];
pMyClass = new (raw_mem) MyClass;
// ...
pMyClass-->(~MyClass());
delete[] raw_mem;
You're not crazy. I have definitely seen an int parameter in a destructor before. Using HP's compiler on OpenVMS, I compiled a sample program show below. The list of symbols does include an destructor with an int parameter. I can only guess this is compiler specific.
$ create foo.cxx
class foo
{
~foo() {}
};
$ cxx foo.cxx
$ type [.CXX_REPOSITORY]cxx$demangler_db.
CX3$_ZN3FOOD1EV31GNTHJ foo::$complete$~foo()
CX3$_ZN3FOOD2EV30KQI3A foo::$subobject$~foo()
CX3$_ZN3FOOD9EV36HH9SB foo::~foo(int)
CXXL$_ZDLPV void operator delete(void *)