0

考虑以下 c++ 代码

class A
{
public:
  void doStuff() {};
  void callStuff()
  {
    doStuff(true);
    doStuff();
  };
private:
  void doStuff(bool doIt = false) {};
};

int main()
{
  A a;
  a.doStuff();
  a.callStuff();

  return 0;
}

毫不奇怪,GCC 在编译时给出了几个错误:

重载.cpp:在成员函数'void A::callStuff()'中:                                                                                                                                                                                                                        
重载.cpp:8:10:错误:重载“doStuff()”的调用不明确                                                                                                                                                                                                          
  做东西();                                                                                                                                                                                                                                                                   
          ^                                                                                                                                                                                                                                                                    
过载.cpp:8:10:注意:候选人是:                                                                                                                                                                                                                                       
重载.cpp:4:12:注意:无效 A::doStuff()                                                                                                                                                                                                                                     
       无效 doStuff() {};                                                                                                                                                                                                                                                      
            ^                                                                                                                                                                                                                                                                  
重载.cpp:11:12: 注意: void A::doStuff(bool)                                                                                                                                                                                                                                
       无效 doStuff(bool doIt = false) {};
            ^
重载.cpp:在函数'int main()'中:
重载.cpp:17:17:错误:重载“doStuff()”的调用不明确
       a.doStuff();
                 ^
过载.cpp:17:17:注意:候选人是:
重载.cpp:4:12:注意:无效 A::doStuff()
       无效 doStuff() {};
            ^
重载.cpp:11:12: 注意: void A::doStuff(bool)
       无效 doStuff(bool doIt = false) {};
            ^

我有几个问题:

  • 如何告诉编译器我想使用哪个重载?我会被迫删除其中一个吗?
  • 如果我必须删除其中一个,如何在编译时找到这个问题而不尝试调用重载?只要我不调用它们,一切都应该编译得很好,所以我以后可能会发现,一旦我试图调用它,我就无法调用我添加的重载。
  • 为什么会出现第二个错误?该main函数不应该能够访问私有重载,因此它应该知道使用哪一个。
4

3 回答 3

2

如何告诉编译器我想使用哪个重载?我会被迫删除其中一个吗?

您不能,只需删除或重命名其中之一。

如果我必须删除其中一个,如何在编译时找到这个问题而不尝试调用重载?只要我不调用它们,一切都应该编译得很好,所以我以后可能会发现,一旦我试图调用它,我就无法调用我添加的重载。

你也不能。仅当您尝试不使用参数调用成员函数时才会检测到歧义。即使您可以执行一些编译时检查,也必须非常具体,并且仅删除或重命名其中一个重载会更容易。

为什么会出现第二个错误?main 函数不应该能够访问私有重载,所以它应该知道使用哪一个。

不幸的是,重载决议在考虑访问说明符之前发生。因此,编译器甚至没有考虑其中一个重载是私有的这一事实:甚至在此之前就发现了模棱两可的调用。我真的不知道为什么会这样,但这就是标准所说的。

于 2013-08-29T02:53:30.377 回答
1

您所有问题的原因都与您的函数定义及其相应的调用有关。

因此,首先,编译器是正确的,因为您的函数调用不明确,因此您的错误 - 因为它无法根据您的使用情况区分需要哪个版本。虽然成员函数可以重载,但在同一范围内具有相同名称,但它们必须具有不同的签名(成员函数的签名由成员函数的名称以及成员函数参数的类型和顺序组成)。

因此:

void doStuff() {};
void doStuff(bool doIt = false) {};

当这样调用时:

doStuff();

是等价的,导致函数调用不明确,因为编译器无法确定您是否要调用:

void doStuff();

或者

void doStuff(boo doIt = false);

带有未提供的参数值。由于同样的问题,无法检查函数可见性。

唯一的解决方法是更改​​其中一个函数的名称函数的签名(同时保持相同的名称)。

因此,这样的事情是完全合法的:

class A
{
public:
  void doStuff() {};
  void callStuff()
  {
    doStuff(1, true);
    doStuff();
  };
private:
  void doStuff(int i, bool doIt = false) {};
};

int main()
{
  A a;
  a.doStuff();
  a.callStuff();

  return 0;
}

因此:

  1. 更改其中一个函数的名称或其签名以及相应的函数调用。
  2. 你不能,因为这是一个模棱两可的电话。唯一的解决方案是进行上述建议的更改。
  3. 什么姆方塔尼尼说

不幸的是,重载决议在考虑访问说明符之前发生。因此,编译器甚至没有考虑其中一个重载是私有的这一事实:甚至在此之前就发现了歧义。

请参阅此链接以获取更多参考:

http://www.learncpp.com/cpp-tutorial/77-default-parameters/

于 2013-08-29T03:10:20.110 回答
0

您需要删除默认参数“bool doIt = false”。

class A
{
public:
  void doStuff() {};
  void callStuff()
  {
    doStuff(true);
    doStuff();
  };
private:
  //void doStuff(bool doIt = false) {};
  void doStuff(bool doIt) {};
};

int main()
{
  A a;
  a.doStuff();
  a.callStuff();

  return 0;
}
于 2013-08-29T08:09:05.683 回答