首页 文章

函数重载在C中通过值或引用传递参数

提问于
浏览
11

如果我们在C中有这个示例函数代码

void foo(int x)  { std::cout << "foo(int)"   << std::endl; }
void foo(int& x) { std::cout << "foo(int &)" << std::endl; }

是否可以区分调用哪些函数在调用参数中进行任何修改?

如果以某些方式调用函数foo:

foo( 10);

i = 10;
foo( static_cast<const int>(i));

foo( static_cast<const int&>(i));

它被称为第一个foo重载函数,因为它不能通过引用将const参数传递给非const参数 . 但是,如何调用第二个foo重载函数呢?如果我打电话给下一个方式:

int i = 10;
foo( i);

它发生了一个模糊的错误,因为这两个函数对这个参数都有效 .

在这个链接https://stackoverflow.com/a/5465379/6717386它's explained one way to resolve it: using objects instead of built-in types and doing private the copy constructor, so it can' t做一个对象值的副本,它必须被称为第二个foo重载函数并通过引用传递对象 . 但是,内置类型有什么办法吗?我必须更改函数名称以避免重载?

5 回答

  • 12

    你可以做一个演员(函数)来选择重载函数:

    static_cast<void (&)(int&)>(foo)(i);
    

    Demo

  • 1

    在大多数情况下,函数重载涉及不同的参数类型和不同的输入参数长度 .

    您的尝试通常是一种不好的做法,由此产生的编译代码依赖于编译器,代码优化甚至可能使事情恶化 .

    您可以考虑 simply 向第二个方法添加第二个参数,如下所示:

    void foo(int x)  { std::cout << "foo(int)"   << std::endl; }
    void foo(int& x, ...) { std::cout << "foo(int &, ...)" << std::endl; }
    

    其中 ... 可以是布尔类型,例如: bool anotherFunction

    因此,调用 foo(param1, param2) 只会调用第二个代码,每个人都可以 .

  • 4

    非常奇怪的设计,但如果你想...我将提供一个像你的设计一样奇怪的解决方案在函数签名中使用Xreference . 然后在函数中,您可以使用 std::is_lvalue_referencestd::is_rvalue_reference 检查您需要执行的操作 .
    像这样的东西

    template<class T>
    void foo(T&& x)
    {
      static_assert(std::is_same<std::decay_t<T>, int>::value, "!"); 
      if (std::is_rvalue_reference<T&&>::value)
        std::cout << "do here what you want in foo(int x)";
      else
        std::cout << "do here what you want in foo(int & x)";
    }
    
    int main()
    {
      int x = 5;
      foo(x); //"do here what you want in foo(int x)" - will be printed
      foo(std::move(x)); //"do here what you want in foo(int & x)" - will be printed
    }
    
  • 4

    尽管@ Jarod42得到了很好的答案,但作为替代解决方案,您可以依赖模板化入口点和内部函数的重载(当然,如果您不想处理显式强制转换) .
    它遵循一个最小的工作示例:

    #include<type_traits>
    #include<iostream>
    #include<utility>
    
    void foo_i(char, int x)  { std::cout << "foo(int)"   << std::endl; }
    void foo_i(int, int &x) { std::cout << "foo(int &)" << std::endl; }
    
    template<typename T>
    void foo(T &&t) {
        static_assert(std::is_same<std::decay_t<T>, int>::value, "!");
        foo_i(0, std::forward<T>(t));
    }
    
    int main() {
        foo( 10);
        int i = 10;
        foo( static_cast<const int>(i));
        foo( static_cast<const int &>(i)); 
        foo(i);
    }
    

    static_assert 用于检查参数是否涉及 int (即 intint &const int & ,int &&`等等) .

    从上面的代码中可以看出, foo(i) 将打印:

    foo(int&)

    正如所料 .

  • 2

    另一个:

    #include <iostream>
    #include <functional>
    
    void foo(int x)
    {
        std::cout << "foo(int)\n";
    }
    
    template<typename T>
    void foo(T&& x)
    {
        std::cout << "foo(int&)\n";
    }
    
    int main()
    {
        int i = 10;
        foo(i);           // foo(int)
        foo(std::ref(i)); // foo(int&)
    }
    

相关问题