Assignment Operator Overload (operator=) - page 2

 
nicholishen:

How exactly is it dangerous? Are you talking about this line? 

It's only dangerous if you forget to delete it, but you'd have that same issue regardless of assignment since you're using pointers to dynamic objects to begin with. This does the same thing as your "Safepointer" example with less lines of code.

I wonder why MQL5 does allow this at all without a compiler error.

Because this isn't java... And you can do it in C++ so naturally mql would inherit the same behavior

By coding:

this = &that;

you're in potential trouble (of getting invalid pointer error somewhere later). Modern C++ does not allow this. MQL5 is designed a la C++ but still lacks many usefull features - this is a (probably temporary) flaw, not a reason for bad coding.

 
Stanislav Korotky:

By coding:

you're in potential trouble (of getting invalid pointer error somewhere later). Modern C++ does not allow this. MQL5 is designed a la C++ but still lacks many usefull features - this is a (probably temporary) flaw, not a reason for bad coding.

Good catch, I missed it. I am surprised it doesn't give a compilation error too.
 
Stanislav Korotky:

By coding:

you're in potential trouble (of getting invalid pointer error somewhere later). Modern C++ does not allow this. MQL5 is designed a la C++ but still lacks many usefull features - this is a (probably temporary) flaw, not a reason for bad coding.

Bad coding? Well let's step back and examine why the compiler isn't complaining, and why the code works, and why there aren't any issues.

Remember when we overloaded the (=) operator in this line?

void operator =(Object *other){ Assign(other);}

What do you suppose the compiler thinks to do when I call this line?

void operator =(Object &other){ this = &other;  }

Well, first it's going to look to see if I have overloaded the (=) operator... and since I have...

void operator =(Object &other){ this = &other;  }  ///This is NOT assignment. This is calling the overloaded operator function
/* calls to */
void operator =(Object *other){ this.Assign(other);}
/* which calls to */
void Assign(Object *other){ this.val=other.val; }

Yes, it is one more step, but I was demonstrating how to overload an operator -- and also how to overload an overloaded operator and use it in the same line. 


I suppose I shall take it as a complement that I was able to stump the coding masters... :) 

 
nicholishen:

Bad coding? Well let's step back and examine why the compiler isn't complaining, and why the code works, and why there aren't any issues.

Remember when we overloaded the (=) operator in this line?

What do you suppose the compiler thinks to do when I call this line?

Well, first it's going to look to see if I have overloaded the (=) operator... and since I have...

Yes, it is one more step, but I was demonstrating how to overload an operator -- and also how to overload an overloaded operator and use it in the same line. 


I suppose I shall take it as a complement that I was able to stump the coding masters... :) 

I am by no way a master in OOP, I used it when I need it and not everywhere, and I have some difficulty to talk OOP in "theory", I mean without a concrete problem to solve.

I will study this topic in deep as it's very interesting, though not a priority.

 
Alain Verleyen:

I am by no way a master in OOP, I used it when I need it and not everywhere, and I have some difficulty to talk OOP in "theory", I mean without a concrete problem to solve.

I will study this topic in deep as it's very interesting, though not a priority.

No worries. I can see where there might be some confusion if you just causally glance at the code. Stanislav thinks it's an assignment when it's actually a method call. Easy mistake to make when you forget the = operator was overloaded.
 

BTW, you can overload any operator and use it the same way I did to get the same net output. Example:

class Object
{
public:
   int val;
   Object(){}
   Object(int v):val(v){}
   void Assign(Object *other){ this.val=other.val; } 
   void operator <<(Object &other){ this << &other;  }
   void operator <<(Object *other){ Assign(other);  } 
   Object* AssignNew(){ return new Object(val);    } 
};
 
nicholishen:
No worries. I can see where there might be some confusion if you just causally glance at the code. Stanislav thinks it's an assignment when it's actually a method call. Easy mistake to make when you forget the = operator was overloaded.

No one except you will support this code. If the code is included in a larger project, it's very easy to screw all things up. For example, you don't have const in any of your assignment menthods, and if someone added it for reference assignment (const Object &other), your pointer overload will magically stop working and you'll get stackoverflow. Also operators could be probably virtual and the class can have descendants. Then this direct assignment will work differently depending from derived stuff.

Strangely you asked if there is a more efficient way for implementation of similar stuff in a parallel thread, yet you describe the trick with double call of overloads, which is excessive, inefficient, and hard to read. Why not to call Assign directly? This is a rhetoric question. Don't bother to answer.

Personally I don't want to resolve ambiguities in my mind on every line of code. Code should be clear and without side effects. The power of OOP is great, but this is a double-endged sword - it can be easily abused.

 
Stanislav Korotky:

No one except you will support this code. If the code is included in a larger project, it's very easy to screw all things up. For example, you don't have const in any of your assignment menthods, and if someone added it for reference assignment (const Object &other), your pointer overload will magically stop working and you'll get stackoverflow. Also operators could be probably virtual and the class can have descendants. Then this direct assignment will work differently depending from derived stuff.

Strangely you asked if there is a more efficient way for implementation of similar stuff in a parallel thread, yet you describe the trick with double call of overloads, which is excessive, inefficient, and hard to read. Why not to call Assign directly? This is a rhetoric question. Don't bother to answer.

Personally I don't want to resolve ambiguities in my mind on every line of code. Code should be clear and without side effects. The power of OOP is great, but this is a double-endged sword - it can be easily abused.


Hold on... you said my code was dangerous and error prone. Now you say that it's just your personal preference? And const params would break an overridden method call...What??! Do you still think that {this = &other} is a pointer assignment? It's a method call not a "pointer overload". And no, adding const doesn't break it, and here's proof. 

class Object
{
public:
   int val;
   Object(){}
   Object(const int v):val(v){}
   void Assign(const Object *other){ this.val=other.val; } 
   void operator =(const Object &other){ this = &other;  } 
   void operator =(const Object *other){ Assign(other);  } 
   Object* AssignNew(){ return new Object(val);    } 
};

void OnStart()
{
   // All valid
   Object a(10),b;
   b=a;
   Object *c = new Object();
   c=b;
   Object *d = c.AssignNew();
   Object obj = d;
   Print("Object obj.val = ",obj.val);
   //this
   a=d;
   //is the same as this
   a.Assign(d);
   delete c;
   delete d;
}

I wouldn't normally call an overridden operate in such way, but in this case it provided an opportunity to cleverly demonstrate to OP how you can override an operator more than once while using it in line with the declaration. I use it sparingly, but it is necessary when all of your code is in the function block of the overloaded operator, like so.

class Object
{
public:
   int val;
   Object(){}
   Object(const int v):val(v){} 
   void operator =(const Object &other){ this = &other;} 
   void operator =(const Object *other){ this.val=other.val;} 
};

This is how I would normally do this routine. This requires the least amount resources. 


So let's talk safe. You provided no evidence of any "error" proneness, but in your example, you assign a statically allocated object to your "SafePointer".

void OnStart()
{
  Object obj1(10);
  Object *obj2;
  Object obj3 = obj1; // copy constructor, not an assignment!
  SafePointer<Object> obj4;
  
  obj2 = &obj1;
  obj4 = &obj1;

  Print(&obj1, " ", obj2, " ", &obj3, " ", ~obj4);
}


What happens when that static object runs out of scope and automatically gets destroyed while your pointer is still addressed to it? Invalid pointer error.

 

This is exactly what I don't want to run into - meaningless debates. You're posting edits of your code, which is not what I talked about. I don't have time to re-write it for you.

My code was not in any message stated as error prone, but it does not have the error you pointed out.

You're free to code as you wish, just don't ask that anyone like it.

 
Stanislav Korotky:

This is exactly what I don't want to run into - meaningless debates. You're posting edits of your code, which is not what I talked about. I don't have time to re-write it for you.

My code was not in any message stated as error prone, but it does not have the error you pointed out.

You're free to code as you wish, just don't ask that anyone like it.

I edited my code to add "const" prove that my code wouldn't break as you asserted. I am wrong, however, your safe pointer class won't produce the invalid pointer error since it doesn't offer any public access to the class. I too am guilty of not spending enough time understanding your code.
Reason: