C++ 运算符重载的基本规则和习惯用法是什么?
注意:答案是按特定顺序给出的,但由于许多用户根据投票而不是给出的时间对答案进行排序,因此以下是答案的索引,以最有意义的顺序排列:C++ 运算符重载的基本规则和习惯用法是什么?,c++,operators,operator-overloading,c++-faq,C++,Operators,Operator Overloading,C++ Faq,注意:答案是按特定顺序给出的,但由于许多用户根据投票而不是给出的时间对答案进行排序,因此以下是答案的索引,以最有意义的顺序排列: 赋值运算符 输入和输出运算符 函数调用运算符 比较运算符 算术运算符 数组下标 类指针类型的运算符 (注意:这是一个条目。如果您想对在此表单中提供常见问题解答的想法提出批评,则可以在此处进行评论。该问题的答案将在中进行监控,其中常见问题解答的想法首先从中开始,因此您的答案很可能会被提出此想法的人阅读。) C++中运算符重载的三个基本规则 在C++中运
- 赋值运算符
- 输入和输出运算符
- 函数调用运算符
- 比较运算符
- 算术运算符
- 数组下标
- 类指针类型的运算符
基本上,重载操作符的首要规则的核心是:不要这样做。这可能看起来很奇怪,因为关于运算符重载还有很多需要了解的地方,所以很多文章、书籍章节和其他文本都涉及到了这一切。但是,尽管这似乎是显而易见的证据,但只有少数情况下操作符重载是合适的。原因是,实际上很难理解运算符应用程序背后的语义,除非在应用程序域中使用运算符是众所周知且无可争议的。与普遍的看法相反,情况几乎从未如此
C++对过载操作符的语义没有限制。编译器将乐于接受实现二进制
+
运算符以从其右操作数中减去的代码。然而,这种运算符的用户决不会怀疑表达式a+b
从b
中减去a
。当然,这假定应用程序域中运算符的语义是无可争议的
操作员之间以及与其他操作相关。如果您的类型支持
a+b
,则用户也可以调用a+=b
。如果它支持前缀增量++a
,那么他们希望a++
也能工作。如果他们能够检查a
,他们肯定也希望能够检查a>b
。如果他们可以复制您的类型,他们希望赋值也能起作用
继续.< /P> C++中运算符重载的三个基本规则 <>在C++中运算符重载时,有< >强> >三个基本规则。与所有这些规则一样,确实存在例外情况。有时人们会偏离这些准则,结果也不错,但这种积极的偏离很少。至少,在我所看到的100个这样的偏差中,有99个是没有道理的。然而,这也可能是千分之999。所以你最好遵守以下规则
基本上,重载操作符的首要规则的核心是:不要这样做。这可能看起来很奇怪,因为关于运算符重载还有很多需要了解的地方,所以很多文章、书籍章节和其他文本都涉及到了这一切。但是,尽管这似乎是显而易见的证据,但只有少数情况下操作符重载是合适的。原因是,实际上很难理解运算符应用程序背后的语义,除非在应用程序域中使用运算符是众所周知且无可争议的。与普遍的看法相反,情况几乎从未如此
C++对过载操作符的语义没有限制。编译器将乐于接受实现二进制
+
运算符以从其右操作数中减去的代码。然而,这种运算符的用户决不会怀疑表达式a+b
从b
中减去a
。当然,这假定应用程序域中运算符的语义是无可争议的
操作员之间以及与其他操作相关。如果您的类型支持
a+b
,则用户也可以调用a+=b
。如果它支持前缀增量++a
,那么他们希望a++
也能工作。如果他们能够检查a
,他们肯定也希望能够检查a>b
。如果他们可以复制您的类型,他们希望赋值也能起作用
继续。运算符重载的一般语法
X& X::operator=(X rhs)
{
swap(rhs);
return *this;
}
std::ostream& operator<<(std::ostream& os, const T& obj)
{
// write obj to stream
return os;
}
std::istream& operator>>(std::istream& is, T& obj)
{
// read obj from stream
if( /* no valid object of T found in stream */ )
is.setstate(std::ios::failbit);
return is;
}
class foo {
public:
// Overloaded call operator
int operator()(const std::string& y) {
// ...
}
};
foo f;
int a = f("hello");
inline bool operator==(const X& lhs, const X& rhs){ /* do actual comparison */ }
inline bool operator!=(const X& lhs, const X& rhs){return !operator==(lhs,rhs);}
inline bool operator< (const X& lhs, const X& rhs){ /* do actual comparison */ }
inline bool operator> (const X& lhs, const X& rhs){return operator< (rhs,lhs);}
inline bool operator<=(const X& lhs, const X& rhs){return !operator> (lhs,rhs);}
inline bool operator>=(const X& lhs, const X& rhs){return !operator< (lhs,rhs);}
bool operator<(const X& rhs) const { /* do actual comparison with *this */ }
class X {
X& operator++()
{
// do actual increment
return *this;
}
X operator++(int)
{
X tmp(*this);
operator++();
return tmp;
}
};
class X {
X& operator+=(const X& rhs)
{
// actual addition of rhs to *this
return *this;
}
};
inline X operator+(X lhs, const X& rhs)
{
lhs += rhs;
return lhs;
}
class X {
value_type& operator[](index_type idx);
const value_type& operator[](index_type idx) const;
// ...
};
class X {
value_type& operator[](index_type idx);
value_type operator[](index_type idx) const;
// ...
};
class my_ptr {
value_type& operator*();
const value_type& operator*() const;
value_type* operator->();
const value_type* operator->() const;
};
enum Month {Jan, Feb, ..., Nov, Dec}
void* operator new(std::size_t) throw(std::bad_alloc);
void operator delete(void*) throw();
void* operator new[](std::size_t) throw(std::bad_alloc);
void operator delete[](void*) throw();
class X { /* ... */ };
char buffer[ sizeof(X) ];
void f()
{
X* p = new(buffer) X(/*...*/);
// ...
p->~X(); // call destructor
}
void* operator new(std::size_t,void* p) throw(std::bad_alloc);
void operator delete(void* p,void*) throw();
void* operator new[](std::size_t,void* p) throw(std::bad_alloc);
void operator delete[](void* p,void*) throw();
class my_class {
public:
// ...
void* operator new();
void operator delete(void*,std::size_t);
void* operator new[](size_t);
void operator delete[](void*,std::size_t);
// ...
};
class my_string {
public:
operator const char*() const {return data_;} // This is the conversion operator
private:
const char* data_;
};
void f(const char*);
my_string str;
f(str); // same as f( str.operator const char*() )
void f(my_string&);
void f(const char*);
f(my_string());
class my_string {
public:
explicit operator const char*() const {return data_;}
private:
const char* data_;
};
prog.cpp: In function ‘int main()’:
prog.cpp:15:18: error: no matching function for call to ‘f(my_string)’
prog.cpp:15:18: note: candidates are:
prog.cpp:11:10: note: void f(my_string&)
prog.cpp:11:10: note: no known conversion for argument 1 from ‘my_string’ to ‘my_string&’
prog.cpp:12:10: note: void f(const char*)
prog.cpp:12:10: note: no known conversion for argument 1 from ‘my_string’ to ‘const char*’
struct Foo
{
int a;
double b;
std::ostream& operator<<(std::ostream& out) const
{
return out << a << " " << b;
}
};
Foo f = {10, 20.0};
std::cout << f;
Foo f = {10, 20.0};
f << std::cout
struct Foo
{
int a;
double b;
};
std::ostream& operator<<(std::ostream& out, Foo const& f)
{
return out << f.a << " " << f.b;
}
Foo f = {10, 20.0};
std::cout << f;