类方法自称为最佳实践

时间:2017-09-22 15:01:51

标签: c++ class structure

考虑以下两个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();
    }
}

如您所见,FooBar具有不同的架构。

这些例子非常基础,但我们可以开始看到两者的somme问题。

对于FoogetElement()验证位置,因此如果我们在已经进行验证时调用它(例如在getLastElement()中),那么它会完成两次。

对于Bar,有很多&#34;代码重复&#34;,如果我们想要修改元素的访问方式,我们必须在进行访问的所有方法中执行此操作。 (而不仅仅是在getElement()示例中调整Foo。)

最好的设计是可维护和可读的。有没有办法解决这个设计问题,没有混合两种风格并保持一致?

有点偏离主题的问题,在这个类operator=(XXX)之类的C ++调用运算符中是否更好,或者像*this = XXX;那样(在Foo::operator!=示例中)?

编辑:删除评论中建议的this->限定符。

2 个答案:

答案 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)来调用所谓的超函数。