- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
注意:答案按特定顺序给出,但由于许多用户根据投票而不是给出时间对答案进行排序,这里是 答案索引按照它们最有意义的顺序:
最佳答案
常用运算符重载
重载运算符的大部分工作是样板代码。这并不奇怪,因为操作符只是语法糖,它们的实际工作可以由(并且经常被转发到)普通函数来完成。但重要的是你要正确地获得这个样板代码。如果你失败了,要么你的运算符(operator)的代码不能编译,要么你的用户的代码不能编译,要么你的用户的代码表现得令人惊讶。
赋值运算符
关于分配有很多话要说。然而,大部分内容已经在GMan's famous Copy-And-Swap FAQ中说到了。 ,所以我会在这里跳过大部分内容,只列出完美的赋值运算符以供引用:
X& X::operator=(X rhs)
{
swap(rhs);
return *this;
}
<<
和
>>
,虽然仍然用于硬件接口(interface)以实现它们从 C 继承的位操作函数,但在大多数应用程序中作为重载的流输入和输出运算符变得更加普遍。有关作为位操作运算符重载的指导,请参阅下面有关二进制算术运算符的部分。当您的对象与 iostreams 一起使用时,要实现您自己的自定义格式和解析逻辑,请继续。
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;
}
operator>>
,只有在读取本身成功时才需要手动设置流的状态,但结果不是预期的。
this
成员函数的参数。除此之外,它可以被重载以接受任意数量的附加参数,包括零。
class foo {
public:
// Overloaded call operator
int operator()(const std::string& y) {
// ...
}
};
foo f;
int a = f("hello");
!
应该(根据相同的规则)作为成员函数来实现。 (但重载通常不是一个好主意。)
std::sort()
)和类型(例如
std::map
)将始终只期望
operator<
在场。但是,您类型的用户也希望所有其他运算符都存在,因此如果您定义
operator<
,请务必遵循运算符重载的第三条基本规则,并定义所有其他 bool 比较运算符。实现它们的规范方法是这样的:
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);}
||
、
&&
)的语法遵循比较运算符的规则。但是,您不太可能为这些 2 找到合理的用例。
*this
, 需要是
const
, 也。因此,作为成员函数实现的比较运算符必须具有以下签名:
bool operator<(const X& rhs) const { /* do actual comparison with *this */ }
const
。)
||
的内置版本和
&&
使用快捷语义。而用户定义的(因为它们是方法调用的语法糖)不使用快捷语义。用户会期望这些操作符具有快捷语义,并且他们的代码可能依赖于它,因此强烈建议永远不要定义它们。
class X {
X& operator++()
{
// do actual increment
return *this;
}
X operator++(int)
{
X tmp(*this);
operator++();
return tmp;
}
};
i++
,很难记住做
++i
相反,当
i
不是内置类型(而且在更改类型时您必须更改代码),因此最好养成始终使用前缀增量的习惯,除非明确需要后缀。
+
,还提供
+=
, 如果您提供
-
, 不要省略
-=
等。据说 Andrew Koenig 是第一个观察到复合赋值运算符可以用作非复合运算符的基础的人。即运算符
+
根据
+=
实现,
-
根据
-=
实现等等。
+
和它的同伴应该是非成员,而它们的复合赋值对应物(
+=
等),改变它们的左参数,应该是成员。这是
+=
的示例代码和
+
;其他二元算术运算符应该以相同的方式实现:
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;
}
operator+=
每个引用返回其结果,而
operator+
返回其结果的拷贝。当然,返回引用通常比返回拷贝更有效,但在
operator+
的情况下,没有办法绕过复制。当你写
a + b
,您希望结果是一个新值,这就是为什么
operator+
必须返回一个新值。 3
operator+
取其左操作数
通过复制 而不是通过常量引用。其原因与
operator=
的原因相同。每个拷贝取其参数。
~
&
|
^
<<
>>
应该以与算术运算符相同的方式实现。但是,(除了用于输出和输入的重载
<<
和
>>
),重载这些的合理用例很少。
a += b
一般来说,比
a + b
更有效如果可能,应该首选。
class X {
value_type& operator[](index_type idx);
const value_type& operator[](index_type idx) const;
// ...
};
operator[]
返回的数据元素| (在这种情况下,您可以省略非常量变体),您应该始终提供运算符的两个变体。
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;
};
->
运算符,如果
value_type
是
class
(或
struct
或
union
)类型,另一个
operator->()
被递归调用,直到
operator->()
返回一个非类类型的值。
operator->*()
见
this question .它很少使用,因此很少重载。事实上,即使是迭代器也不会重载它。
关于c++ - 运算符重载的基本规则和习惯用法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4421706/
我编写的代码主要供个人使用,但我正在考虑发布我最初开发供个人使用的应用程序(科学模拟/可视化)。 我的一个习惯是在类中使用一个main方法来单独测试类的运行情况。我认为这在某种程度上可能是不好的(毫无
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: How do I convince programmers in my team to do TDD? 在从
假设我想测试是否有一个名为“Z”的驱动器。第一步是这样的; Get-PSProvider | Select-Object -Property Drives 这个给我; Drives: ... {C,
这是对 an old answer to a question about the necessity of functools.partial 的一种跟进: 虽然这个答案非常清楚地解释了这种现象及其
Perl 习惯很难改掉。两种语言之间的变量声明、作用域、全局/局部是不同的。是否有一组推荐的 python 语言习语可以使从 perl 编码到 python 编码的过渡不那么痛苦。 细微的变量拼写错误
我是一名优秀的程序员,十分优秀!