虚函数默认参数和重载 [英] Virtual function default parameters and overloading

查看:295
本文介绍了虚函数默认参数和重载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题涉及这些问题中讨论的常见问题:





虚函数默认参数



下面是c ++中使用虚函数的默认参数时发生的情况: p>

  struct Base 
{
virtual void foo(int one = 1,int two = 2)
{cout< one:<<一个<< two:<<两个< endl; }
};

struct Derived:public Base
{
virtual void foo(int one = 3,int two = 4)
{Base :: foo(one,two) ; cout < 派生! << endl; }
};

int main()
{
Base * b = new Base();
Base * d = new Derived();

Derived * dp = new Derived();

b-> foo();
d-> foo();
dp-> foo();

return 0;
}

输出:

  one:1 two:2 
one:1 two:2
derived!
one:3 two:4
派生!

这是我希望存在于c ++虚拟函数默认参数中的行为:

  #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:<<一个<< two:<<两个< endl; }
};

struct Derived:public Base
{
virtual void foo(){foo(3,4); }
virtual void foo(int one,int two)
{Base :: foo(one,two); cout < 派生! << endl; }
};

int main()
{
Base * b = new Base();
Base * d = new Derived();

Derived * dp = new Derived();

b-> foo();
d-> foo();
dp-> foo();

return 0;
}

输出:

  one:1 two:2 
one:3 two:4
derived!
one:3 two:4
派生!

因此,基本上,如果我想覆盖父类中的默认参数,一个带有这个数量的参数的新foo。请注意,导出的覆盖了no-arg条件,但不覆盖one-arg条件。
注意,我当前的项目使用一个纯虚拟的基类。我经常有基类类型和派生类类型的指针。



p>我已经阅读了很多关于这个主题的问题,但他们似乎都没有给出合理的解决方案。大多数解决方案会在整个项目中产生更丑陋的代码。



有人说不要在虚拟函数上使用默认参数,但是我需要默认在每个地方我调用的函数。似乎最好只是发表一个评论,也改变基类和也改变派生类比在必须改变函数的所有地方。



有人说只有基类中有默认参数,但这意味着在使用默认值之前,需要将任何指向一个派生对象的指针转换回一个基指针。



有没有原因我应该避免上面的设计?

解决方案

在某些时候,你的代码的未来维护者会感到困惑,困惑和/或困惑,如果你改变默认值,取决于它们调用的静态类型 foo

$ p

因为你的担心是有人改变父母的默认值,忘记了使用非虚拟接口模式更新容易解决的子类:

  #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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆