虚函数默认参数和重载 [英] Virtual function default parameters and overloading
问题描述
此问题涉及这些问题中讨论的常见问题:
有人说不要在虚拟函数上使用默认参数,但是我需要默认在每个地方我调用的函数。似乎最好只是发表一个评论,也改变基类和也改变派生类比在必须改变函数的所有地方。
有人说只有基类中有默认参数,但这意味着在使用默认值之前,需要将任何指向一个派生对象的指针转换回一个基指针。
有没有原因我应该避免上面的设计?
在某些时候,你的代码的未来维护者会感到困惑,困惑和/或困惑,如果你改变默认值,取决于它们调用的静态类型 foo
因为你的担心是有人改变父母的默认值,忘记了使用非虚拟接口模式更新容易解决的子类:
#include< iostream>
using namespace std;
struct Base
{
void foo(int one = 1,int two = 2){foo_impl(one,two); }
protected:
virtual void foo_impl(int one,int two)
{cout< one:<<一个<< two:<<两个< endl; }
};
struct派生:public Base
{
protected:
virtual void foo_impl(int one,int two)
{Base :: foo_impl(one,二); cout < 派生! << endl; }
};
int main()
{
Base * b = new Base();
Base * d = new Derived();
Derived * dp = new Derived();
b-> foo();
d-> foo();
dp-> foo();
return 0;
}
This question refers to common problems discussed in these questions:
Can virtual functions have default parameters?
Virtual functions default parameters
Here is what currently happens in c++ with default parameters to virtual functions:
struct Base
{
virtual void foo(int one = 1, int two = 2)
{ cout << "one: " << one << " two: " << two << endl; }
};
struct Derived : public Base
{
virtual void foo(int one = 3, int two = 4)
{ Base::foo(one, two); cout << " derived!" << endl; }
};
int main()
{
Base* b = new Base();
Base* d = new Derived();
Derived* dp = new Derived();
b->foo();
d->foo();
dp->foo();
return 0;
}
output:
one: 1 two: 2
one: 1 two: 2
derived!
one: 3 two: 4
derived!
This is the behaviour I wish existed in c++ virtual function default parameters:
#include <iostream>
using namespace std;
struct Base
{
virtual void foo () { foo(1, 2); }
virtual void foo (int one) { foo(one, 2); }
virtual void foo(int one, int two)
{ cout << "one: " << one << " two: " << two << endl; }
};
struct Derived : public Base
{
virtual void foo() { foo(3, 4); }
virtual void foo(int one, int two)
{ Base::foo(one, two); cout << " derived!" << endl; }
};
int main()
{
Base* b = new Base();
Base* d = new Derived();
Derived* dp = new Derived();
b->foo();
d->foo();
dp->foo();
return 0;
}
output:
one: 1 two: 2
one: 3 two: 4
derived!
one: 3 two: 4
derived!
So, basically, if I want to override a default parameter in a parent class, I will just create a new foo with that number of arguments. Note that the derived overrides the no-arg condition, but not the one-arg condition. As a side note, my current project uses a purely virtual base class. I often have pointers of the base class type and of the derived class type. I want a call from either pointer to have the same result.
QUESTIONS:
I have read many questions related to this subject, but they all don't seem to give reasonable solutions. Most of the solutions would result in uglier code all throughout your project.
Some say "Don't use default parameters on virtual functions," but then I would need to put the default in every place I call the function. It seems it would be better to just put a comment that says, "also change base class" and "also change derived class" than to have to change everywhere the function is called.
Some say to only have the default parameters in the base class, but that means that any pointer to a derived object would need to be cast back to a base pointer before the defaults could be used. That makes a lot of code ugly as well.
Are there reasons I should avoid the above design?
At some point in time future maintainers of your code will be baffled, confused, and/or perplexed if you change the default values depending on which static type they call foo
on so I'm going to assume that's not your concern.
Given that your concern is someone changing the default in the parent and forgetting to update the child class that's easily solved with the non-virtual interface pattern:
#include <iostream>
using namespace std;
struct Base
{
void foo(int one = 1, int two = 2) { foo_impl(one, two); }
protected:
virtual void foo_impl(int one, int two)
{ cout << "one: " << one << " two: " << two << endl; }
};
struct Derived : public Base
{
protected:
virtual void foo_impl(int one, int two)
{ Base::foo_impl(one, two); cout << " derived!" << endl; }
};
int main()
{
Base* b = new Base();
Base* d = new Derived();
Derived* dp = new Derived();
b->foo();
d->foo();
dp->foo();
return 0;
}
这篇关于虚函数默认参数和重载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!