考虑以下两个C ++示例(即使语言无关紧要)。
首先是Foo
类,它会调用自己的方法,例如getSize()
,isPosValid()
,getElement()
。
class Foo {
private:
std::vector<int> elements_ { };
public:
size_t getSize() const {
return elements_.size();
}
bool isPosValid(const size_t pos) const {
return pos < getSize();
}
int getElement(const size_t pos) const {
if (!isPosValid(pos)) {
return 0;
}
return elements_[pos];
}
// Here we could use elements_.back(), but this is just for the example.
int getLastElement() const {
if (getSize() == 0u) {
return 0;
}
return getElement(getSize() - 1u);
}
bool operator==(const Foo& rhs) const {
return getSize() == rhs.getSize();
}
bool operator!=(const Foo& rhs) const {
return !(*this == rhs);
// OR maybe : return !operator==(rhs);
}
}
然后,Bar
类,不会调用自己的方法,但会有一些代码重复。
class Bar {
private:
std::vector<int> elements_ { };
public:
size_t getSize() const {
return elements_.size();
}
bool isPosValid(const size_t pos) const {
return pos < elements_.size();
}
int getElement(const size_t pos) const {
if (pos >= elements_.size()) {
return 0;
}
return elements_[pos];
}
// Here we could use this->elements_.back(), but this is just for the example.
int getLastElement() const {
if (elements_.size() == 0u) {
return 0;
}
return elements_[elements_.size() - 1u];
}
bool operator==(const Bar& rhs) const {
return elements_.size() == rhs.elements_.size();
}
bool operator!=(const Bar& rhs) const {
return elements_.size() != rhs.elements_.size();
}
}
如您所见,Foo
和Bar
具有不同的架构。
这些例子非常基础,但我们可以开始看到两者的somme问题。
对于Foo
,getElement()
验证位置,因此如果我们在已经进行验证时调用它(例如在getLastElement()
中),那么它会完成两次。
对于Bar
,有很多&#34;代码重复&#34;,如果我们想要修改元素的访问方式,我们必须在进行访问的所有方法中执行此操作。 (而不仅仅是在getElement()
示例中调整Foo
。)
最好的设计是可维护和可读的。有没有办法解决这个设计问题,没有混合两种风格并保持一致?
有点偏离主题的问题,在这个类operator=(XXX)
之类的C ++调用运算符中是否更好,或者像*this = XXX;
那样(在Foo::operator!=
示例中)?
编辑:删除评论中建议的this->
限定符。
答案 0 :(得分:0)
一般来说,第一个是更好的设计。您总是想要分解公共代码(如大小检查)并在您的类中重用它。您的示例很简单,但在现实世界中,检查可能不仅仅是查看大小,您还希望将公共逻辑放在一个位置。这只是一个很好的软件设计。
对于逻辑运算符,出于同样的原因,您总是希望以==定义!=。与其他逻辑运算符类似。
此外,使用更自然的等式表达式。使用operator =()函数的可读性要低得多。在我看来,即使是经验丰富的C ++程序员也是如此。
答案 1 :(得分:0)
这是设计的方面,您正在使用并继续使用它。我个人更喜欢*this = XXX
,但当ThisClass& operator =(OtherClass o)
除了将OtherClass
类型的成员分配给新值o
之外什么都没做时,我只是直接在另一个内部访问该成员操作符 - /成员函数。但是,我单独实施operator ==(..)
和operator !=(..)
(天真地快得多),或者我使用自动实现operator !=()
的宏,而operator ==()
已由我实现(不过它如果C ++有一个int operator =?=(ThisClass)
就像strcmp那样工作会更优雅,如果更小则返回-1,如果相等则返回0,如果更大则返回1,并且自动定义其他经典比较运算符)。
#define impl_operator_neq \
template<typename T>
bool operator(T other) { return !(*this == other);
但是我看到了一些天真的代码(这是错误的),它实现了像这样的相等运算符:
bool operator ==(Account const& o) {
return !(*this != o); // the person also tried return *this == o;
};
// ...
bool operator !=(Account const& o) {
return !(*this == o);
};
第一个原本就像以下一样,后来改为那个荒谬的代码:
bool operator ==(Account const& o) {
return !(strcmp(this->name, o.name));
};
因此,在此代码中,最好使用operator xy(..)
来表示它正在调用当前类中的另一个运算符。然而,虽然运算符只是用于调用函数的语法糖,但它们可以是虚拟的并且在类中重载,因此只能通过转换或写this->BaseClass::operator!=(other)
来调用所谓的超函数。