在接口中公开方法但在实现中受保护有什么好处?

发布于 2024-10-01 16:25:18 字数 418 浏览 5 评论 0原文

在我的 C++ 应用程序中,我有一个如下所示的接口:

class ICalculator
   {
   public:
      virtual double calculateValue(double d) = 0;
   };

我有该接口的实现,如下所示:

class MySpecificCalculator
   {
   public:
      virtual double calculateValue(double d);
   };

现在我的同事对此抱怨并告诉我最好保护calculateValue 方法。这样,我们可以保证调用者始终通过接口传递,而不是通过直接实现。

这是正确的观察吗?保护接口的实现真的更好吗?或者我们甚至不能将其设为私有吗?

In my C++ application I have an interface that looks like this:

class ICalculator
   {
   public:
      virtual double calculateValue(double d) = 0;
   };

I have implementations of this interface that look like this:

class MySpecificCalculator
   {
   public:
      virtual double calculateValue(double d);
   };

Now my colleague complains about this and tells me it's better to have the calculateValue method protected. That way, we can guarantee that the callers always pass via the interface and not via the direct implementation.

Is this a correct observation? Is it really better to make the implementation of an interface protected? Or can't we even make it private then?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

决绝 2024-10-08 16:25:18

你的同事是对的。

切勿公开虚拟函数。

准则#1:更喜欢制作
非虚拟接口,使用模板
方法。

准则#2:更喜欢
将虚拟函数设为私有。

准则#3:仅当派生类
需要调用基础实现
的虚函数,使
虚函数受保护。

对于析构函数的特殊情况
仅:

准则#4:基类析构函数
应该是公共的和虚拟的,
或受保护且非虚拟。

Your colleague is right.

Never make virtual functions public.

Guideline #1: Prefer to make
interfaces nonvirtual, using Template
Method.

Guideline #2: Prefer to
make virtual functions private.

Guideline #3: Only if derived classes
need to invoke the base implementation
of a virtual function, make the
virtual function protected.

For the special case of the destructor
only:

Guideline #4: A base class destructor
should be either public and virtual,
or protected and nonvirtual.

街角迷惘 2024-10-08 16:25:18

听起来你同事的意思是:

class ICalculator
{
public:
    virtual double calculateValue(double d) const = 0;
};

class MySpecificCalculator : public ICalculator
{
protected:
    double calculateValue(double d) const;
};

void Calc(double d, const ICalculator& c)
{
    std::cout << "Result = " << c.calculateValue(d) << std::endl;
}

int main ()
{
    MySpecificCalculator c;
    c.calculateValue(2.1);  // dont do this
    Calc(2.1, c);  // do this instead
    return 0;
}

我看不出这个设计有什么好处。为什么不能从具体参考中调用计算。在派生类中将calculateValue 移至protected 会破坏基类的约定。您不能使用 MySpecificCalculator 来计算 Value,但它的基类是这么说的。

顺便说一句,这种行为并不是按照 Chubsdad 解释的 NVI 惯用法建模的(这是“正确”的方式)。

It sounds that your colleague means:

class ICalculator
{
public:
    virtual double calculateValue(double d) const = 0;
};

class MySpecificCalculator : public ICalculator
{
protected:
    double calculateValue(double d) const;
};

void Calc(double d, const ICalculator& c)
{
    std::cout << "Result = " << c.calculateValue(d) << std::endl;
}

int main ()
{
    MySpecificCalculator c;
    c.calculateValue(2.1);  // dont do this
    Calc(2.1, c);  // do this instead
    return 0;
}

I cant see any benefit from this design. Why not to be able to call calculate from a concrete reference. To move calculateValue to protected in the derived class, breaks the contract of the base class. You can't use a MySpecificCalculator to calculate a Value, but its base class says so.

Btw this behaviour is not modeled by the NVI idiom explained by Chubsdad (which is the 'correct' way).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文