【问题标题】:What does the C++ compiler do when coming ambiguous default parameters?当出现模棱两可的默认参数时,C++ 编译器会做什么?
【发布时间】:2011-04-20 23:26:02
【问题描述】:

当出现不明确的默认参数时,C++ 编译器会做什么?例如,假设有一个函数,例如:

void function(int a = 0, float b = 3.1);
void function(int a, float b =1.1, int c = 0);

以上是否被认为是模棱两可的?如果不是,编译器在调用function1(10) 之类的东西时会做什么(函数如何精确匹配)?

谢谢!

【问题讨论】:

  • 你的函数有不同的标识符。没有歧义。你是不是想把它们都命名为function
  • @JoshD:不太可能。第一个有 2 个参数,第二个 - 3。
  • @Andrey:这个问题没有任何意义,除非有模棱两可的,所以乔希的评论是恰当的。
  • @user466152:如果你想知道编译器是否发现函数调用有歧义,只需编译一个测试程序问他。
  • @AndreyT:在 C++ 中,您可以拥有同名的不同函数,前提是它们的签名(本质上是参数和类型)不同。如果他们做了根本不同的事情,那是一种糟糕的风格,但语言中没有任何东西将它们联系在一起。

标签: c++ compiler-construction default-value overloading


【解决方案1】:

如果它们有不同的名称(如您的示例),则没有歧义。如果它们具有相同的名称(因此这是一种重载尝试),编译器会报错。

虽然事实证明你可以在不同的范围内重新定义一个函数的默认参数(这对我来说是个新闻……)——但是在同一个范围内,你不能重新定义默认参数 甚至相同的值。来自 8.3.6/4 “默认参数”:

对于非模板函数,默认 参数可以稍后添加 同一个函数的声明 范围。不同的声明 范围具有完全不同的集合 默认参数。那是, 内部范围内的声明不 获取默认参数 外部范围内的声明,反之亦然 反之亦然。在给定的函数中 声明,所有参数随后 到具有默认参数的参数 应提供默认参数 在这个或以前的声明中。一种 默认参数不应是 由后来的声明重新定义(不是 甚至相同的值)。

【讨论】:

    【解决方案2】:

    模棱两可?您有两个完全独立的不同功能:function1function2。甚至每个函数中的参数数量都不一样。这里没有任何歧义。当您要求编译器调用function1(10) 时,它会调用function1(10, 3.1)function2 甚至没有出现。

    如果是同一个函数,那么歧义问题就不会出现,因为在 C++ 中多次为同一个参数指定默认参数是非法的(在同一个翻译单元内)。即使你们第二次指定相同的默认参数值,程序也是格式错误的

    void foo(int a = 5);
    void foo(int a = 5); // <- ERROR
    

    但可以做的是在不同的翻译单元中为同一函数指定一组不同的默认参数。但这不会产生任何歧义,因为编译器只能看到一个翻译单元。在这种情况下,编译器根本不会知道任何潜在的“歧义”。

    【讨论】:

    • 如果是两个不同的函数,函数名相同怎么办?我认为这就是 OP 的真正含义。
    【解决方案3】:

    以下就可以了

    void function(int a = 0, float b = 3.1);
    void function(int a, float b =1.1, int c = 0);
    

    下面的也不错

    function(); // calls first function
    

    但以下是模棱两可的

    function(1); // second and first match equally well
    

    对于重载决策(告诉调用哪个函数的过程),未传递显式参数和使用默认参数的参数将被忽略。所以编译器确实看到两个函数都有一个用于上述调用的 int 参数并且无法决定。

    以下内容不正确

    void function(int a = 0, float b = 3.1);
    void function(int a, float b =1.1);
    

    虽然对于您问题中的代码,您声明了 两个 函数(因为两个声明具有不同数量的参数),但在此示例中您只声明 一个 函数。但是它的第二个声明重复了参数的默认参数(甚至使用不同的值,但这不再重要了)。这是不允许的。请注意,以下是可以的

    void function(int a, float b = 3.1);
    void function(int a = 0, float b);
    

    出现在同一作用域内的同一函数的声明的默认参数集被合并,并且仅适用于出现在同一作用域内的那些。所以以下是有效的

    void function(int a = 0, float b = 3.1);
    void function1() {
      void function(int a, float b = 1.1); 
      function(0);
    }
    

    这会调用带有1.1 传递给b 的函数。

    【讨论】:

    • 这是 void 函数吗(int a = 0, float b);真的好吗?你确定吗?
    【解决方案4】:

    此外,任何以“C++ 编译器做什么......”开头的问题的答案总是“取决于您所谈论的编译器。”

    【讨论】:

    • 好吧,假设它是 GNU 编译器。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-19
    • 1970-01-01
    • 1970-01-01
    • 2021-01-30
    • 2011-11-27
    • 1970-01-01
    • 2013-11-04
    相关资源
    最近更新 更多