私有方法使用作用域解析运算符是个不好的主意吗?

huangapple go评论59阅读模式
英文:

Why is it a bad idea to use scope resolution operator with a private method?

问题

假设我有一个类

class ClassOne {
    private:
    void methodOne();

    public:
    void methodTwo();
};

现在

void ClassOne::methodOne() { // <-- private
   // other code
}

void ClassOne::methodTwo() { // <-- public
   // other code
   ClassOne::methodOne(); // <-- 使用作用域解析运算符调用私有函数
}

我被告知这是一种不应该做的事情,而应该改为

void ClassOne::methodTwo() { // <-- public
   // other code
   methodOne();              // <-- 直接调用私有函数
}

有人可以解释为什么这不是良好的做法或错误的做法吗?

当我编译时没有错误,所以我想了解可能会出现什么问题。

英文:

Suppose I have some class

class ClassOne {
    private:
    void methodOne();

    public:
    void methodTwo();
};

Now

void ClassOne::methodOne() { // <-- private
   // other code
}

void ClassOne::methodTwo() { // <-- public
   // other code
   ClassOne::methodOne(); // <-- private function called with scope resolution operator
}

I have been told this is something that I shouldn't do and instead to

void ClassOne::methodTwo() { // <-- public
   // other code
   methodOne();              // <-- private function 
}

Can someone explain why this is not goot practice or wrong practice?

When I compile I get no errros, so I want to understand what issue can occur.

答案1

得分: 3

不要重复自己

在软件开发中,有一个通用原则叫做"不要重复自己"(DRY)。最好避免重复信息,因为:

  1. 如果您更新信息(比如类的名称),您将不得不在多个地方进行更改。
  2. 重复的信息没有任何作用。它只是噪音,使读者更难理解代码,因为需要阅读更多内容。
void ClassOne::methodTwo() {
   methodOne();
}

在这个例子中,可以编写ClassOne::methodOne(),甚至::ClassOne::methodOne(),但这完全没有意义。这段代码位于ClassOne的成员函数中,所以我们已经知道methodOne() 可能 是一个成员函数。如果您想要 确定 它是一个成员函数,有更好的表达方式。

明确引用成员的替代方法

如果您想要强调这是一个成员函数,可以:

  • 在成员函数前添加前缀,例如m_methodOne()
  • 访问成员时使用this,即this->methodOne()

这两种方法不会重复类名,但仍强调我们正在使用一个成员函数,使它们更好。

有时,您必须重复类名

请注意,有时您别无选择,只能重复类名以消除歧义。例如,如果您继承自类AB,它们都有一个叫做method()的成员函数,您将不得不编写A::method()B::method()以消除歧义并选择正确的函数。

然而,像这样的情况非常少见。
在这些情况下 使用类名的好处是我们强调了它们,使得不寻常的情况变得明显。

英文:

Don't Repeat Yourself

In software development, there is a general principle called "Don't Repeat Yourself" (DRY).
It's best to avoid repeating information because:

  1. If you update the information (such as the name of the class), you will have to make that change in multiple places.
  2. The repeated information doesn't serve any purpose. It's just noise which makes it harder for the reader to comprehend the code, because there is more to read.
void ClassOne::methodTwo() {
   methodOne();
}

In this example, it is possible to write ClassOne::methodOne() or even ::ClassOne::methodOne(), but it would be totally pointless. This code is located in a member function of ClassOne, so we already know that methodOne() is possibly a member function.
If you want to be certain that it is a member function, there are better ways to express that.

Alternative Ways of Explicitly Referring to Members

If you want to emphasize that it is a member function, you can:

  • add a prefix to your member functions, e.g. m_methodOne()
  • use this when accessing members, i.e. this->methodOne()

These two methods don't repeat the class name, but still emphasize that we are using a member function, making them much better.

Sometimes, You Must Repeat the Class Name

Note that sometimes, you are left with no other choice than to repeat the class name, in order to disambiguate.
For example, if you inherit from to classes A and B which both have a member function called method(), you will have to write A::method() or B::method() to disambiguate and choose the right one.

However, situations like that are very uncommon.
Using the class name only in these cases has the added benefit that we're emphasizing them and making it obvious that something unusual is taking place.

huangapple
  • 本文由 发表于 2023年6月22日 03:23:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76526516.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定