S6 Operator Overloading
文章目录
Basic Concepts
Operator overloading allows you to define operator behavior for custom types
Definition
Operator overloading enables users to extend the definitions of C++ operators to work with user-defined types.
Purpose
- Improves code readability
- Makes operations more intuitive
- Enables more natural programming expressions
⠀
General Format of Operator Overloading
ReturnType operator OperatorSymbol(ParameterList)
{
// Function body
}
Example: Overloading the “+” Operator
class Complex {
private:
double real;
double imag;
public:
Complex(double r = 0, double i = 0) : real(r), imag(i) {}
// Overloading + operator
Complex operator + (const Complex& other) {
Complex result;
result.real = this->real + other.real;
result.imag = this->imag + other.imag;
return result;
}
};
// Usage
Complex a(1, 2);
Complex b(3, 4);
Complex c = a + b; // Equivalent to a.operator+(b)
Two Forms of Operator Overloading
Member Function Form | Friend Function Form |
---|---|
ReturnType operator+(Args) | friend ReturnType operator+(Args) |
Left operand is the object itself | Both operands are parameters |
Uses this to access object members | Needs friend declaration to access private members |
Member Function Form
class Vector {
private:
double x, y;
public:
Vector(double a = 0, double b = 0) : x(a), y(b) {}
Vector operator + (const Vector& v) {
return Vector(x + v.x, y + v.y);
}
};
Friend Function Form
class Vector {
private:
double x, y;
public:
Vector(double a = 0, double b = 0) : x(a), y(b) {}
friend Vector operator + (const Vector& a, const Vector& b);
};
Vector operator + (const Vector& a, const Vector& b) {
return Vector(a.x + b.x, a.y + b.y);
}
Special Operator Overloading
1. Assignment Operator (=)
class String {
private:
char* data;
public:
String& operator = (const String& other) {
if (this == &other) return *this; // Self-assignment check
delete[] data; // Free existing memory
data = new char[strlen(other.data) + 1]; // Allocate new memory
strcpy(data, other.data); // Copy data
return *this; // Return self-reference
}
};
Notes:*this == String &
Example:
class Name{
public:
Name(){pname=0;}
Name(char *pn){copyname(pn);}
Name(Name&s ){copyname(s.pname);}
~ Name(){deleteName();}
Name& operator =(Name& s)
{if (this ==&s) return *this ;
deleteName(); copyname(s.pname);
return *this; }
void display()
{cout<<pname<<endl;}
protected:
void copyname(char *pn);
void deleteName();
char *pname;};
void Name::copyname(char *p)
{pname=new char[strlen(p)+1];
if (pname)
{strcpy(pname,p);}
}
void Name::deleteName()
{if (pname)
{delete[] pname;
pname=0;}}
void main()
{Name s("Jenny");
Name t("kite");
Name n(t); n.display();
t=s; t.display(); //t.operator=(s);
t=s=Name("jacky");
t.display();
(t=n)=s; t.display(); }
2. Increment/Decrement Operators (++/–)
// Prefix increment (returns reference)
Counter& operator ++ () {
value++;
return *this;
}
// Postfix increment (returns value)
Counter operator ++ (int) { //(int) means the overload is postfix
Counter temp = *this;
value++;
return temp;
}
Example:
class aa{
float a; float b;
public:
float &aaa(){return(a);}
float &bbb(){return(b);}
aa operator ++(int);
};
aa aa::operator ++(int){
aa m(*this); a=a+1; b=b+1; return(m);
}
void main()
{ aa a;
a.aaa()=1; a.bbb()=2;
cout<<a++.aaa()<<endl;//a.operator++(1);//1
cout<<a.aaa()<<endl; //2 }
3. Subscript Operator ([])
T& operator [] (int index) {
return array[index];
}
4. Function Call Operator (())
ReturnType operator () (Parameters) {
// Function body
}
5. Type Conversion Operator
operator TargetType() {
// Convert current object to target type and return
return someValue;
}
class aa{
float a; float b;
public:
float &aaa(){return(a);}
float &bbb(){return(b);}
operator float();
};
aa::operator float() { return(a);}
void main()
{ aa a,b;
a.aaa()=1; a.bbb()=2;
b.aaa()=3; b.bbb()=4;
cout<<float(a)<<endl; //a.operator float();
cout<<10+a<<endl;
cout<<a+b<<endl;
cout<<a<<endl;}
Rules for Operator Overloading
Overloadable Operators | Non-overloadable Operators |
---|---|
+, -, *, /, % | . (member selection) |
==, !=, <, >, <=, >= | .* (member object selection) |
++, – | :: (scope resolution) |
=, +=, -=, *=, /=, %= | ?: (conditional) |
[], () | sizeof |
->, ->* | typeid |
new, delete | .* |
&, |, ^, ~, <<, >> |
Important Rules
1 At least one operand must be a user-defined type
2 Cannot change the operator precedence or associativity
3 Cannot create new operators
4 Some operators can only be overloaded as member functions: =, [], (), ->
5 Some operators are typically overloaded as friend functions: <<, >>
6 It’s not recommended to change the basic meaning of operators
7 No default parameters allowed in overloaded operator functions
⠀
Practical Applications of Operator Overloading
String Class with Operator Overloading
class MyString {
private:
char* str;
int length;
public:
MyString(const char* s = NULL);
MyString(const MyString& other);
~MyString();
// Overload + operator for string concatenation
MyString operator + (const MyString& other) const;
// Overload = operator for string assignment
MyString& operator = (const MyString& other);
// Overload == operator for string comparison
bool operator == (const MyString& other) const;
// Overload subscript operator []
char& operator [] (int index);
};
Smart Pointer with Operator Overloading
template <typename T>
class SmartPtr {
private:
T* ptr;
public:
SmartPtr(T* p = nullptr) : ptr(p) {}
~SmartPtr() { delete ptr; }
// Overload * operator
T& operator * () const { return *ptr; }
// Overload -> operator
T* operator -> () const { return ptr; }
// Overload = operator
SmartPtr& operator = (const SmartPtr& other);
};
#OOP