14. 运算符重载
14.1 Overloaded operator
- Just a function with an operator name!
- Use the
operator
keyword as a prefix to nameoperator *(...)
- Use the
- Can be a member function
- Implicit first argument
this
:
const String String::operator +(const String& that);
- Implicit first argument
- Can be a global (free) function
- Both arguments explicit
const String operator+(const String& r, const String& l);
- Both arguments explicit
14.2 参数传入
- If it is read-only, pass it in as a const reference.
- Make member functions const that don't change the class(boolean operators, +, -, etc)
- For global functions, if the left-hand side changes pass as a reference(assignment operators)
14.3 结果返回
- Select the return type depending on the expected meaning of the operator. For example,
- For operator+ you need to generate a new object. Return as a const object so the result cannot be modified as an lvalue.
- Logical operators should return bool(or int for older compilers)
14.4 The prototypes of operators
+-*/%^&|~
const T operatorX(const T& left, const T& right) const;
!&&||< <= == >= >
bool operatorX(const T& left, const T& right) const;
[]
T& T::operator[](int index);
operators ++ and --
- Postfix forms take an int argument -- compiler will pass in 0 as that int
class Integer {
public:
const Integer& operator++(); // prefix++
const Integer operator++(int); // postfix++
const Integer& operator--(); // prefix--
const Integer operator--(int); // postfix--
};
const Integer& Integer::operator++() {
*this += 1;
return *this;
}
const Integer Integer::operator++(int) {
Integer old(*this);
++(*this);
return old;
}
- Relation operators
- implement
!=
in terms of==
- implement
>, >=, <=
in terms of<
- implement
class Integer {
public:
bool operator==(const Integer& rhs) const;
bool operator!=(const Integer& rhs) const;
bool operator<(const Integer& rhs) const;
bool operator>(const Integer& rhs) const;
bool operator<=(const Integer& rhs) const;
bool operator>=(const Integer& rhs) const;
}
bool Integer::operator==(const Integer& rhs) const {
return i == rhs.i;
}
bool Integer::operator!=(const Integer& rhs) const {
return !(*this == rhs);
}
bool Integer::operator<(const Integer& rhs) const {
return i < rhs.i;
}
// implement lhs > rhs in terms of lhs < rhs
bool Integer::operator>(const Integer& rhs) const {
return rhs < *this;
}
// implement lhs <= rhs in terms of !(rhs < lhs)
bool Integer::operator<=(const Integer& rhs) const {
return !(rhs < *this);
}
// implement lhs >= rhs in terms of !(lhs < rhs)
bool Integer::operator>=(const Integer& rhs) const {
return !(*this < rhs);
}
14.5 赋值
- 示例:
class Fi {
public:
Fi(){}
};
class Fee {
public:
Fee(int) {}
Fee(const Fi&){}
};
int main() {
Fee fee = 1; // Fee(int)
Fi fi;
// 拷贝构造
Fee fum = fi; // Fee(Fi)
// 赋值
fum = fi;
}
14.5.1 Assignment Operator
- Must be a member function
- Will be generated for you if you don't provide one
- Same behavior as automatic copy constructor -- memberwise assignment
- Check for assignment to self
- Be sure to assign to all data members
- Return a reference to
*this
T& T::operator=(const T& rhs) {
// check for self assignment
if (this != &rhs) {
// perform assignment
}
return *this;
}
14.6 类型转换
- A conversion operator can be used to convert an object of one class into
- an object of another class
- a built-in type
- Compilers perform implicit conversions using:
- Single-argument constructors
- implicit type conversion operators
14.6.1 Single-argument constructors
- 示例:
class PathName {
string name;
public:
PathName(const string&);
~PathName();
};
int main()
{
string abc("abc");
PathName xyz(abc); // OK, 拷贝构造
xyz = abc; // OK, abc => PathName
}
// 示例二:
class One {
public:
One(){}
};
class Two {
public:
Two(const One&) {}
};
void f(Two) {}
int main() {
One one;
f(one); // Wants a Two, has a One
}
14.6.2 Preventing implicit conversions
explicit
关键字- 示例:
class PathName {
string name;
public:
explicit PathName(const string&);
~ PathName();
};
int main()
{
string abc("abc");
PathName xyz(abc); // OK!
xyz = abc; // Error!
}
14.6.3 Conversion operations
-
Operator conversion
- Function will be called automatically
- Return type is same as function name
-
格式:
X::operator T()
- Operator name is any type descriptor
- No explicit arguments
- No return type
- Compiler will use it as a type conversion from
X => T
-
示例:
class Rational {
public:
operator double() const; // Rational to double
};
Rational::operator double() const {
return numrator_/(double)denominator_;
}
int main()
{
Rational r(1, 3);
double d = 1.3 * r; // r => double
}
参考资料: