C++ 良好实践:纯虚方法的默认参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12139786/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:55:46  来源:igfitidea点击:

Good practice : Default arguments for pure virtual method

c++

提问by deimus

I have created an abstract base class, which has a pure virtual method with default argument.

我创建了一个抽象基类,它有一个带有默认参数的纯虚方法。

class Base {
    ...
    virtual someMethod(const SomeStruct& t = 0) = 0;
    ...
}

class Derived : public Base {
    ...
    virtual someMethod(const SomeStruct& t = 0);
    ...
}

So I would like to know is it a good practice to set the default argument to pure virtual and overall to virtual methods?

所以我想知道将默认参数设置为纯虚拟并将整体设置为虚拟方法是否是一个好习惯?

采纳答案by edA-qa mort-ora-y

I often wish to use both default parameters and virtual function as you do. The others have rightfully pointed out however that this leads to ambiguity and is generally not a good idea. There is a reasonably simple solution, one that I use. Give your virtual function a different name, make it protected, and then provide a public function with default parameters which calls it.

我经常希望像您一样使用默认参数和虚函数。然而,其他人正确地指出,这会导致歧义,通常不是一个好主意。有一个相当简单的解决方案,我使用的一个。给你的虚函数一个不同的名字,让它受到保护,然后提供一个带有默认参数的公共函数来调用它。

class Base {
protected:
    virtual void vSomeMethod(const SomeStruct& t ) = 0;
public:
    void someMethod( const SomeStruc& t = 0 )
    { vSomeMethod( t ); }
}

Derived classes simply override vSomeMethodand don't worry at all about the default parameters.

派生类只是覆盖vSomeMethod,根本不用担心默认参数。

回答by Mihails Strasuns

Actually, your code is one of worst possible usage patterns for default parameters, as it involves both inheritance and polymorphic behavior. I support an advice to have a look at related Scott Meyers tip, but here is a short overview:

实际上,您的代码是默认参数最糟糕的使用模式之一,因为它涉及继承和多态行为。我支持查看相关 Scott Meyers 提示的建议,但这里有一个简短的概述:

In case of polymorphic calls, default parameters are used according to declaration for static type, not dynamic one. It is logical as run-time has no idea of default parameters, but breaks any sane assumptions about polymorphic behavior. For example,

在多态调用的情况下,根据静态类型的声明使用默认参数,而不是动态类型。这是合乎逻辑的,因为运行时不知道默认参数,但打破了关于多态行为的任何合理假设。例如,

#include <cstdio>

class Base
{
        public:
                virtual void f(int a = 1)
                {
                        printf("Base::f(%d)\n", a);
                }
};

class Deriv : public Base
{
        public:
                virtual void f(int a = 2)
                {
                        printf("Deriv::f(%d)\n", a);
                }
};

int main()
{
        Base* a = new Deriv();
        a->f();
        delete a;
        return 0;
}

yields:

产量:

Deriv::f(1)

回答by Seb Rose

Don't use default parameters at all if possible, but if you do, never redefine them (see the text for details)

如果可能,根本不要使用默认参数,但如果使用,请永远不要重新定义它们(有关详细信息,请参阅文本

Buy both the Effective C++ books by Scott Meyers. You won't regret it.

购买 Scott Meyers 的 Effective C++ 书籍。你不会后悔的。

回答by Paolo Brandoli

I would:

我会:

  • define the virtual functions with the parameter (without default value)
  • define non virtual functions in the base class, without parameter at all, that call the virtual function passing the correct default parameter
  • 用参数定义虚函数(无默认值)
  • 在基类中定义非虚函数,完全没有参数,调用传递正确默认参数的虚函数

This way the derived classes don't have to care about the default value at all.

这样派生类根本不必关心默认值。

回答by Emilio Garavaglia

If you want this code to make sense:

如果您希望此代码有意义:

Base* p = new Derived;
p->someMethod();

since the static type of pis Base*it is the Base signature that is used on call. The default value is assigned and, being the function virtual, the call is redirected to Derived.

因为静态类型的pBase*它是在调用中使用的基本特征。分配了默认值,并且作为函数 virtual,调用被重定向到 Derived。

You can even have them defined differently, if you want your Derived::someMethod to receive a different value from Base*rather than Derived*...

如果您希望 Derived::someMethod 从而Base*不是从Derived*...

The important thing is document these "relations" well, since the most of programmers will not understood them from a simple reading of the code.

重要的是要很好地记录这些“关系”,因为大多数程序员不会通过简单的代码阅读来理解它们。

Of course, if all that is not suitable in you particular context, generating more confusion than else, avoid default parameters on virtual functions, and use helper non-virtual one to call them properly.

当然,如果所有这些都不适合您的特定上下文,会产生更多的混乱,请避免虚函数上的默认参数,并使用辅助非虚函数正确调用它们。

But considering also that -by a reader standpoint- a default parameter is more explicative than a overload function calling privately another with a not readable parameter rework.

但也要考虑到——从读者的角度来看——默认参数比重载函数以不可读的参数返工私下调用另一个函数更具说明性。