如何选择正确的过载?

时间:2013-08-29 02:48:30

标签: c++ overloading

考虑以下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在编译时会出现几个错误:

overload.cpp: In member function ‘void A::callStuff()’:                                                                                                                                                                                                                        
overload.cpp:8:10: error: call of overloaded ‘doStuff()’ is ambiguous                                                                                                                                                                                                          
  doStuff();                                                                                                                                                                                                                                                                   
          ^                                                                                                                                                                                                                                                                    
overload.cpp:8:10: note: candidates are:                                                                                                                                                                                                                                       
overload.cpp:4:12: note: void A::doStuff()                                                                                                                                                                                                                                     
       void doStuff() {};                                                                                                                                                                                                                                                      
            ^                                                                                                                                                                                                                                                                  
overload.cpp:11:12: note: void A::doStuff(bool)                                                                                                                                                                                                                                
       void doStuff(bool doIt = false) {};
            ^
overload.cpp: In function ‘int main()’:
overload.cpp:17:17: error: call of overloaded ‘doStuff()’ is ambiguous
       a.doStuff();
                 ^
overload.cpp:17:17: note: candidates are:
overload.cpp:4:12: note: void A::doStuff()
       void doStuff() {};
            ^
overload.cpp:11:12: note: void A::doStuff(bool)
       void doStuff(bool doIt = false) {};
            ^

我有几个问题:

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

3 个答案:

答案 0 :(得分:2)

  

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

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

  

如果我必须删除其中一个,我怎么能找到这个问题   编译时没有试图调用重载?只要我不是   调用它们的一切都应该编译好,所以我可能只会发现   后来我无法调用我曾经添加的超载   试着打电话。

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

  

为什么会出现第二个错误?主要功能不应该   访问私有超载,以便它应该知道使用哪一个。

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

答案 1 :(得分: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. mfontanini said
  4.   

    不幸的是,在访问说明符之前会发生重载解析   考虑到了。因此,编译器甚至不参与   考虑到其中一个重载是私有的这一事实:模糊性   在发生之前就已经发现了。

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

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

答案 2 :(得分: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;
}