代码之家  ›  专栏  ›  技术社区  ›  mp.

在C++中,在函数的定义中,参数标识符是可选的。在哪种情况下,此功能可能有用?

c++
  •  5
  • mp.  · 技术社区  · 14 年前
    int foo(int){      
         ...  
    }
    

    有什么想法吗?

    8 回复  |  直到 14 年前
        1
  •  7
  •   Community CDub    7 年前

    在Scott Meyers的“有效C++,第三版”中,定义了一个函数但不命名参数的一个例子,项目47:

    template<typename IterT, typename DistT>        
    void doAdvance(IterT& iter, DistT d,            
                   std::random_access_iterator_tag) 
    {
      iter += d;
    }
    

    用于:

    template<typename IterT, typename DistT>
    void advance(IterT& iter, DistT d)
    {
      doAdvance( iter, d, 
                 typename std::iterator_traits<IterT>::iterator_category() );
    }
    

    实际上,doadvance中的第三个参数是一个没有变量名的类型,即它是一个未命名的参数。拥有一个未命名的参数不是问题,因为该参数只在重载函数的解析过程中使用。我在 this 相关的问题。

        2
  •  11
  •   Ed Swangren    14 年前

    当您实际上不在函数中使用参数,但不想破坏公共方法签名时。

        3
  •  4
  •   Joel    14 年前

    这就是编译器如何区分后缀和前缀增量运算符——x operator++()是前缀,x operator++(int)是后缀。

    因为int从未在postfix操作符中实际使用过,所以没有理由给它起个名字。这就是为什么你会得到未命名的参数,来重载一个函数或操作符来表示两个稍微不同的东西。这是loki和boost中使用的模板元编程中的常见技巧。

        4
  •  3
  •   David Thornley    14 年前

    在某些情况下,编译器会警告未使用的参数,除非您在显示时不使用标识符名称。显示一个参数未使用也是很有用的。除此之外,我不知道。如果使用该参数,则不能将标识符保留为关闭状态。

        5
  •  2
  •   user401947    14 年前

    可以使用其他参数 SFINAE ,用于根据类型属性进行过载解析或调度。

    #include <boost/utility/enable_if.hpp>
    #include <boost/type_traits.hpp>
    #include <boost/call_traits.hpp>
    #include <iostream>
    #include <string>
    
    // use SFINAE enable this function for numerical types only
    template <class T>
    double foo(T t, typename
                    boost::enable_if<boost::is_floating_point<T> >::
                    type* dummy = 0) {
        double x = static_cast<double>(t);
        return x;
    }
    
    // use extra parameter for overload resolution
    struct PlanA {};
    struct PlanB {};
    
    void bar(const PlanA&) {
        std::cout << "using plan A...\n";
    }
    
    void bar(const PlanB&) {
        std::cout << "using plan B...\n";
    }
    
    // use type traits to choose which function to call
    template <typename T>
    double fooBar(T t) {
        return dispatch(t, boost::is_convertible<T, double>());
    }
    
    double dispatch(double t, const boost::true_type&) {
        std::cout << "convertible to double\n";
        return t+0.1;
    }
    
    template <typename T>
    double dispatch(const T&, const boost::false_type&) {
        std::cout << "not convertible to double\n";
        return 0.0;
    }
    
    
    int main () {
    
        foo(1.0);
        // foo(1); won't compile
    
        bar(PlanA());
        bar(PlanB());
    
        std::string name = "John Dow";
    
        fooBar(1.0);
        fooBar(name);
    }
    
        6
  •  1
  •   Edward Strange    14 年前

    当您正在实现某个签名的函数时,实际上不需要参数(在抽象的层次结构中非常常见),并且需要在不发出警告的情况下进行编译。由于所有项目都应该设置为在出现警告时中断,而这在oop/gp中经常出现,所以这是一个非常非常常见的事情。事实上,很多库都有一个mylibunused()宏来提高易读性,这是很常见的。

        7
  •  1
  •   sbi    14 年前

    注意,由于编译器不关心实际的参数名,所以您可以使用 不同的参数名 函数(模板)的声明而不是其定义。

    当您有一个作为头文件和lib文件发送的库,并且每个使用API的人都不希望仅仅因为在库中更改了某些参数的名称而重新编译所有内容时,这是非常有用的。(你可能已经在多MLC+C++项目中欣赏了这一点。)

        8
  •  0
  •   Baltasarq    14 年前

    我认为你的意思是在函数声明中。实际上,您也可以在函数定义中省略标识符名称,但是如果使用参数,这将导致编译错误,这很可能发生。