Object reading and writing overload in C++ - c++

I know that the assignment operator can be overloaded. When writing to an object, the object's overload function is called.
Obj = 10; // Obj's assignment overload function called.
Is there a way to define a function to be called when an object is read?
int a = Obj;
In this case Obj's reading function would be called and the return value would be assigned to a.

You're looking for what's sometimes called a cast operator.
example:
#include <iostream>
struct example
{
int val;
operator int() const { return val; }
};
int main ()
{
example x{42};
int y = x;
std::cout << y;
}
Will print 42.

Related

Why in below code return type is class type used for operator overloading?

I have been trying to understand operator overloading and did not get the use of return type as class type in the below program:
When I switch "overload" return type with "int" it works fine.
#include <iostream>
using namespace std;
class overload {
private:
int count;
public:
overload(int i)
: count(i)
{
}
overload operator++(int) //why return type is class type when i can use int
{
return (count++);
}
overload operator++() //why return type is class type when i can use int
{
count = count + 1;
return count;
}
void Display()
{
cout << "Count: " << count<<endl;
}
};
// Driver code
int main()
{
overload i(5);
overload post(5);
overload pre(5);
// this calls "function overload operator ++()" function
pre = ++i;
post = i++;
i.Display();
return 0;
}
The difference between the pre/post increment operators is that one works on the object directly (pre-increment: ++foo), and one needs to take a copy of the object and return that (post increment: foo++). A slightly more verbose way of writing this would be:
// return a new object that represents the old value
overload operator++(int)
{
overload oldValue(count); // take copy
count++; // increment this object
return oldValue;
}
// increment the count, and return a reference to this object
overload& operator++()
{
++count;
return *this;
}
Whilst you could return int (don't do that!), it will only lead to confusion. Effectively it would cause a few issues with code such as:
overload foo = ++someOtherFoo;
Which if you were to return int from ++, would effectively end up calling your constructor function (rather than copy constructor) to construct a new object. i.e.
overload foo = overload(++someOtherFoo);
That constructor might not be available, and so the code would fail.
If you want your object to automatically convert itself to an integer, then the correct way would be to overload the cast operator, e.g.
operator int () const
{
return count;
}
There are no restrictions on the return type of an overloaded operator. Here it can be int as well.
The code you show has the class type as return type to facilitate the other statements in the code as below if ever the constructor of the overload class is marked explicit;
For example with:
explicit overload(int i)
: count(i)
{
}
and
int operator++(int) //return type is int
{
return (count++);
}
int operator++() //return type is int
{
count = count + 1;
return count;
}
The following will fail to compile:
pre = ++i; //will not work
post = i++; //will not work
This is because the implicit copy assignment operator will no longer be viable for conversion from int to const overload.
See Demo
Note that the Canonical implementations of the prefix and postfix increment/decrement operators return overload& and overload respectively.
Although canonical form of pre-increment/pre-decrement returns a reference, as with any operator overload, the return type is user-defined; for example the overloads of these operators for std::atomic return by value

c++ using the = operator with objects

One operation that continues to confuse me in C++ is how operator= interacts with objects.
I'm not sure what exactly is occurring behind the scenes when executing a program such as this:
class ObjectType {
private:
int variable;
public:
ObjectType(int v) {
variable = v;
}
};
int main() {
ObjectType object1(10);
ObjectType object2(15);
object1 = object2;
return 0;
}
From my understanding, it makes all of the member variables in the first object equal to the corresponding member variables in the second object. In this case, the "variable" of object1 would now equal 15, but I'm not sure.
Any elaborations would be greatly appreciated, thank you.
When you type object1 = object2; Here it invokes = operator overloaded function, if operator overloading function for assignment operator is not
defined , then compiler does it for us by-default ,the compiler just does a member-wise copy from one object to another object.
Here is basic code :
class ObjectType {
private:
int variable;
public:
ObjectType(int v) {
variable = v;
}
void operator () (int n1){ /** () operator overloaded function if needed **/
variable = n1;
}
};
int main() {
ObjectType object1(10);//parameterized constructor will be called
ObjectType object2(15);
/** use case when () operator overloaded function will be called
ObjecType object1;
object1(10);// invokes () overloaded function
**/
object1 = object2;/** if = operator overloaded function is not defined then consider default one provided by compiler */
return 0;
}

Pointer to member operator

I have this link http://www.codingunit.com/unary-and-binary-operator-table. It says that pointer to member operator is a binary operator.
I have this code :
class test
{
public:
int num;
test(int j)
{
num=j;
}
test* operator->()
{
this->num;
}
};
int main()
{
test T(5);
cout<<"Number is :"<<T->num;
}
As I know, non static member function of binary operator accepts one argument, but according to this program if I provide it one argument. It has an error, which says that test* operator ->(int x) should be test* operator ->(void) .
To get the expected result, you need to change your program as follows:
test* operator->()
{
return this;
}
};
int main()
{
test T(5);
cout<<"Number is :"<<T->num;
}
In your operator overloading function, you should return this pointer. Since your operator overloaded function for -> does not accept a parameter, so when you call it you don't need to pass a parameter value. So function call should be T->num;

What does *this = NULL mean inside a method in a templated class?

Inside a templated class, I found the expression, *this = NULL What does such an expression mean ?
The following is its definition:
TYPE** getPtr()
{
*this = NULL;
return &m_pPtr;
}
where m_pPtr is type TYPE* in the template class.
Assignment operator:
// Assignment operator.
TYPE* operator =(TYPE *pPtr) {
if (pPtr == m_pPtr)
return pPtr;
m_pPtr = pPtr;
return m_pPtr;
}
Vishnu.
It's difficult to say what the point of such a statement is without seeing the actual code.
But it will probably be invoking an overloaded assignment operator. e.g.:
#include <iostream>
class X {
public:
void operator=(void *) {
std::cout << "Here!\n";
}
void foo() {
*this = NULL;
}
};
int main() {
X x;
x.foo();
}
It's attempting to assign 0 to the current object. It will call something like
operator=(void *);
Another possibility (as far as I know) is that there is a constructor in the object which takes a void* or similar type. Then it would construct an object and then copy-assign that.
T :: T(void *); // construct with the void *
T :: T(const T &); // copy assignment

How do I create a class that can initialize C++ data types?

The title basically says it all. I mainly want to do this so that I can create an object (say, a custom string object) that can initialize the parameters of other functions in other APIs. Here's an example of me trying to get a custom integer class to work:
#include <iostream>
using namespace std;
class test
{
public:
int member;
test(int i) : member(i) {}
friend int &operator=(int &i, test t);
};
int &operator=(int &i, test t)
{
return (i = t.member);
}
int main()
{
int i;
test t = 90;
cout << (i = t);
return 0;
}
Unfortunately I receive an error saying that operator= needs to be a member function. I understand the C++ standard's goal in preventing static and non-member overloads for the assignment operator from being implemented, but is there any other way to do this? Thanks for any help/suggestions!
This is not done with an assignment operator but with an overloaded typecast. This would make your main function work like expected:
#include <iostream>
using namespace std;
class test
{
public:
int member;
test(int i) : member(i) {}
operator int() const {return member;}
};
int main()
{
int i;
test t = 90;
cout << (i = t);
return 0;
}
What you are trying to do needs an conversion operator
operator int()
{
return this->member;
}
For the class you are trying to write(containing only integer members), You do not need to overload the = operator.
= operator is one of the member functions that is generated by the compiler by default for every class. Caveat is, it does a simple bit by bit copy(shallow copy) of class members, since you have only integers it should be good enough for you.
You would need to overload the = operator if you had dynamically allocated pointers as member functions, because in that case a shallow copy of those pointers would result in all the objects containing a member pointer pointing to the same dynamic memory location & if one of the object finishes it lifetime, other objects are left with a dangling pointer.
As #Tony, aptly points in out comments Shallow copy is usually bad but not always. See his comments for a scenario.
If at all you want to overload the assignment operator check out the Copy and Swap Idiom to do it right way.
You should also check out the Rule of Three.
Try this:
class test
{
public:
int member;
test(int i) : member(i) {}
operator int() {return this->member;}
};
int main(void)
{
int i;
test t = 90;
cout << (i = t);
return 0;
}
The assignment operator cannot be a friend function. The assignment operator can only be declared as a non-static member function. This is to ensure that it receives the L-value as its first operand. The same is true for the [], (), and -> operators. In your case, since int is an build-in type, you cannot use member function. You can implement operator int() to cast your user-defined type to int.