虚函数可以有默认参数吗?
如果我声明一个基类(或接口类)并为其一个或多个参数指定默认值,则派生类是否必须指定相同的默认值,如果不是,哪些默认值将在派生类中体现?
附录:我也对如何跨不同编译器处理此问题以及在这种情况下“推荐”实践的任何输入感兴趣。
If I declare a base class (or interface class) and specify a default value for one or more of its parameters, do the derived classes have to specify the same defaults and if not, which defaults will manifest in the derived classes?
Addendum: I'm also interested in how this may be handled across different compilers and any input on "recommended" practice in this scenario.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
虚拟可能有默认值。基类中的默认值不会被派生类继承。
使用哪个默认值——即基类“还是派生类”——由用于调用函数的静态类型决定。如果通过基类对象、指针或引用进行调用,则使用基类中表示的默认值。相反,如果通过派生类对象、指针或引用进行调用,则使用派生类中表示的默认值。标准报价下方有一个示例说明了这一点。
某些编译器可能会执行不同的操作,但这就是 C++03 和 C++11 标准的规定:
这是一个示例程序,用于演示采用的默认值。为了简洁起见,我在这里使用
struct
而不是class
——class
和struct
正是除了默认可见性之外,几乎所有方面都相同。该程序的输出(在 MSVC10 和 GCC 4.4 上)是:
Virtuals may have defaults. The defaults in the base class are not inherited by derived classes.
Which default is used -- ie, the base class' or a derived class' -- is determined by the static type used to make the call to the function. If you call through a base class object, pointer or reference, the default denoted in the base class is used. Conversely, if you call through a derived class object, pointer or reference the defaults denoted in the derived class are used. There is an example below the Standard quotation that demonstrates this.
Some compilers may do something different, but this is what the C++03 and C++11 Standards say:
Here is a sample program to demonstrate what defaults are picked up. I'm using
struct
s here rather thanclass
es simply for brevity --class
andstruct
are exactly the same in almost every way except default visibility.The output of this program (on MSVC10 and GCC 4.4) is:
这是 Herb Sutter 早期的一篇本周大师帖子的主题。
他就这个问题说的第一句话是“不要那样做”。
更详细地说,是的,您可以指定不同的默认参数。它们的工作方式与虚拟函数不同。虚函数是在对象的动态类型上调用的,而默认参数值是基于静态类型的。
鉴于
你应该得到
答::foo1
B::foo2
B::foo1
This was the topic of one of Herb Sutter's early Guru of the Week posts.
The first thing he says on the subject is DON'T DO THAT.
In more detail, yes, you can specify different default parameters. They won't work the same way as the virtual functions. A virtual function is called on the dynamic type of the object, while the default parameter values are based on the static type.
Given
you should get
A::foo1
B::foo2
B::foo1
这是一个坏主意,因为您获得的默认参数将取决于对象的静态类型,而分派到的
虚拟
函数将取决于动态 类型。也就是说,当您使用默认参数调用函数时,无论该函数是否为虚拟函数,默认参数都会在编译时被替换。
@cppcoder 在他的[已关闭]问题中提供了以下示例:
产生以下输出:
借助上面的解释,很容易看出原因。在编译时,编译器会替换指针静态类型的成员函数中的默认参数,使
main
函数等效于以下内容:This is a bad idea, because the default arguments you get will depend on the static type of the object, whereas the
virtual
function dispatched to will depend on the dynamic type.That is to say, when you call a function with default arguments, the default arguments are substituted at compile time, regardless of whether the function is
virtual
or not.@cppcoder offered the following example in his [closed] question:
Which produces the following output:
With the aid of the explanation above, it is easy to see why. At compile time, the compiler substitutes the default arguments from the member functions of the static types of the pointers, making the
main
function equivalent to the following:正如其他答案所详述的那样,这是个坏主意。然而,由于没有人提到简单有效的解决方案,这里是:将参数转换为结构体,然后您可以将默认值设置为结构体成员!
所以,不要这样做
,
As other answers have detailed, its bad idea. However since no one mentions simple and effective solution, here it is: Convert your parameters to struct and then you can have default values to struct members!
So instead of,
do this,
正如您从其他答案中看到的,这是一个复杂的主题。而不是尝试这样做或理解它的作用(如果你现在必须问,维护者将不得不在一年后询问或查找它)。
相反,应在基类中使用默认参数创建一个公共非虚函数。然后,它调用一个私有或受保护的虚拟函数,该函数没有默认参数,并根据需要在子类中重写。那么你就不必担心它如何工作的细节,而且代码非常明显。
As you can see from the other answers this is a complicated subject. Instead of trying to do this or understand what it does (if you have to ask now, the maintainer will have to ask or look it up a year from now).
Instead, create a public non-virtual function in the base class with default parameters. Then it calls a private or protected virtual function that has no default parameters and is overridden in child classes as needed. Then you don't have to worry about the particulars of how it would work and the code is very obvious.
您可能可以通过测试很好地弄清楚这一点(即,它是该语言的足够主流的部分,大多数编译器几乎肯定都能正确执行,除非您看到编译器之间的差异,否则它们的输出可以被认为是相当权威的)。
This is one that you can probably figure out reasonably well by testing (i.e., it's a sufficiently mainstream part of the language that most compilers almost certainly get it right and unless you see differences between compilers, their output can be considered pretty well authoritative).