当前位置:  开发笔记 > 编程语言 > 正文

可选函数参数:使用默认参数(NULL)或重载函数?

如何解决《可选函数参数:使用默认参数(NULL)或重载函数?》经验,为你挑选了5个好方法。

我有一个处理给定向量的函数,但如果没有给出,也可以自己创建这样的向量.

我看到这种情况有两种设计选择,其中一个函数参数是可选的:

将它设为指针并NULL默认设置为:

void foo(int i, std::vector* optional = NULL) {
  if(optional == NULL){
    optional = new std::vector();
    // fill vector with data
  }
  // process vector
}

或者有两个带有重载名称的函数,其中一个省略了参数:

void foo(int i) {
   std::vector vec;
   // fill vec with data
   foo(i, vec);
}

void foo(int i, const std::vector& optional) {
  // process vector
}

是否有理由选择一种解决方案而不是另一种?

我稍微偏爱第二个,因为我可以将向量作为const引用,因为它在提供时只能读取而不能写入.此外,界面看起来更干净(NULL不仅仅是一个黑客?).并且间接函数调用产生的性能差异可能会被优化掉.

然而,我经常在代码中看到第一个解决方案.除了程序员的懒惰之外,是否有令人信服的理由更喜欢它?



1> John Dibling..:

我不会使用任何一种方法.

在这种情况下,foo()的目的似乎是处理一个向量.也就是说,foo()的工作是处理向量.

但是在foo()的第二个版本中,隐含地给出了第二个工作:创建向量.foo()版本1和foo()版本2之间的语义不一样.

而不是这样做,我会考虑只有一个foo()函数来处理一个向量,而另一个函数创建向量,如果你需要这样的东西.

例如:

void foo(int i, const std::vector& optional) {
  // process vector
}

std::vector* makeVector() {
   return new std::vector;
}

显然这些函数是微不足道的,如果所有makeVector()需要做的就是完成它的工作就完全是调用new,那么使用makeVector()函数可能没有意义.但我确信在你的实际情况下,这些函数比这里显示的更多,而我上面的代码说明了语义设计的基本方法:给一个函数做一个工作.

我上面提到的foo()函数的设计也说明了我个人在我的代码中使用的另一种基本方法,当涉及到设计接口时 - 包括函数签名,类等等.这就是:我相信一个好的接口是1)容易和直观正确使用,2)难以或不可能错误地使用.在foo()函数的情况下,我们隐含地说,根据我的设计,向量必须已经存在并且已经"准备好".通过设计foo()来获取引用而不是指针,调用者必须已经有一个向量是直观的,并且他们将很难传递一些不是现成的向量.


在C++ 11中返回uniqe_ptr,或按值返回.

2> LeopardSkinP..:

我绝对赞成重载方法的第二种方法.

第一种方法(可选参数)模糊了方法的定义,因为它不再具有明确定义的目的.这反过来又增加了代码的复杂性,使不熟悉代码的人更难理解代码.

使用第二种方法(重载方法),每种方法都有明确的目的.每种方法都具有良好的结构凝聚力.一些额外的说明:

如果需要将代码复制到两个方法中,则可以将其提取到单独的方法中,并且每个重载方法都可以调用此外部方法.

我会更进一步,并以不同的方式命名每个方法,以指示方法之间的差异.这将使代码更加自我记录.


我对这个答案没问题,但我不同意你的推理.重载点是_each方法已经做同样的事情_,这就是为什么我们不关心通过名称来区分它们.通常,重载只会在它们接受的_type_参数中有所不同 - 会出现一组`print(int)`,`print(double)`类型的函数.在有可选的返回参数的情况下,这应该只意味着调用者可能会或可能不关心rx该可选结果.我同意这个答案中的最后一句话:如果函数执行不同的操作,那么__yes,将每个方法命名为__._

3> David Ruhman..:

虽然我确实理解许多人对默认参数和过载的抱怨,但似乎对这些功能提供的好处缺乏了解.

默认参数值:
首先,我想指出,在项目的初始设计中,如果设计得很好,默认情况应该几乎没有用.但是,默认情况下,最大的资产发挥作用的是现有项目和完善的API.我从事包含数百万现有代码行的项目,并且无需重新编写所有代码.因此,当您希望添加需要额外参数的新功能时; 新参数需要默认值.否则,您将破坏使用您项目的每个人.哪个对我个人没问题,但我怀疑你的公司或产品/ API的用户会喜欢在每次更新时重新编码他们的项目. 简单来说,默认值非常适合向后兼容! 这通常是您将在大API或现有项目中看到默认值的原因.

函数覆盖:函数覆盖 的好处是它们允许共享功能概念,但具有不同的选项/参数.但是,很多时候我看到函数覆盖延迟用于提供截然不同的功能,只是略有不同的参数.在这种情况下,它们应该各自具有与其特定功能相关的单独命名的功能(与OP的示例一样).

这些c/c ++的功能很好,并且在正确使用时效果很好.这可以说是大多数编程功能.当他们被滥用/滥用时,他们会导致问题.

免责声明:
我知道这个问题已经有几年了,但是由于今天(2012年)我的搜索结果中出现了这些答案,我觉得这需要进一步解决未来的读者问题.



4> Sid Sarasvat..:

C++中的引用不能为NULL,一个非常好的解决方案是使用Nullable模板.这会让你做的事情是ref.isNull()

在这里你可以使用这个:

template
class Nullable {
public:
    Nullable() {
        m_set = false;
    }
    explicit
    Nullable(T value) {
        m_value = value;
        m_set = true;
    }
    Nullable(const Nullable &src) {
        m_set = src.m_set;
        if(m_set)
            m_value = src.m_value;
    }
    Nullable & operator =(const Nullable &RHS) {
        m_set = RHS.m_set;
        if(m_set)
            m_value = RHS.m_value;
        return *this;
    }
    bool operator ==(const Nullable &RHS) const {
        if(!m_set && !RHS.m_set)
            return true;
        if(m_set != RHS.m_set)
            return false;
        return m_value == RHS.m_value;
    }
    bool operator !=(const Nullable &RHS) const {
        return !operator==(RHS);
    }

    bool GetSet() const {
        return m_set;
    }

    const T &GetValue() const {
        return m_value;
    }

    T GetValueDefault(const T &defaultValue) const {
        if(m_set)
            return m_value;
        return defaultValue;
    }
    void SetValue(const T &value) {
        m_value = value;
        m_set = true;
    }
    void Clear()
    {
        m_set = false;
    }

private:
    T m_value;
    bool m_set;
};

现在你可以拥有

void foo(int i, Nullable &optional = Nullable()) {
   //you can do 
   if(optional.isNull()) {

   }
}



5> 小智..:

我同意,我会使用两个功能.基本上,您有两种不同的用例,因此有两种不同的实现是有意义的.

我发现我编写的C++代码越多,我的参数默认值就越少 - 如果该功能被弃用,我真的不会流泪,尽管我不得不重新编写一堆旧代码!

推荐阅读
无名有名我无名_593
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有