【问题标题】:C++ Ambigous call to constructorC++ 对构造函数的模糊调用
【发布时间】:2015-05-22 08:16:51
【问题描述】:

我有一个包含多个构造函数和重载运算符的类:

class Utf8String
{
public:

   Utf8String();

   explicit Utf8String( const char * sStr );

   Utf8String( const char * sStrBeg, const char * sStrEnd );

   Utf8String( const char * sStr, uint32_t nCpCount );

   explicit Utf8String( const Utf8String & sStr );

   explicit Utf8String( const Utf8String & sStr, uint32_t nStart = 0, uint32_t nCpCount = UINT32_MAX );

   Utf8String( uint32_t nCpCount, uchar32_t cCodePoint );

   explicit Utf8String( long int iVal );

   explicit Utf8String( double fVal );

   // More stuff

   inline Utf8String operator + ( const char * sStr ) const
   {
      Utf8String sRes( *this ); // ERROR
      return sRes += sStr;
   }

   inline operator const char * () const;

   inline operator char * ();

   inline operator long int () const;

   inline operator double () const;
};

由于某种原因,我收到了一个错误:

Error   3   error C2668: 'core::Utf8String::Utf8String' : ambiguous call to overloaded function c:\xxx\utf8string.h 280

我尝试在似乎有意义的地方添加显式关键字。我还向所有构造函数添加了显式,只是为了看看会发生什么,但无论我做什么,我都会收到这个错误并且无法找出原因。

你有什么想法吗?谢谢。

【问题讨论】:

  • utf8string.h 280 是哪一行?
  • // ERROR注释的,也是唯一一个包含实现代码的。
  • 您收到错误是因为两个构造函数与调用匹配。 Utf8String(const Utf8String& sStr)Utf8String(const Utf8String& sStr, uint32_t nStart = 0, uint32_t nCpCount = UINT32_MAX) 都是不错的候选人。这是不允许的。您需要定义一个复制构造函数,而不是两个。

标签: c++ constructor operator-overloading implicit-conversion explicit


【解决方案1】:

这两个功能:

explicit Utf8String( const Utf8String & sStr );

explicit Utf8String( const Utf8String & sStr, uint32_t nStart = 0, uint32_t nCpCount = UINT32_MAX );

不应同时存在。它们会导致问题。

由于第二个构造函数的其余参数都有默认值,如果只传递一个参数,它们会导致模棱两可的错误,如下所示:

 Utf8String s = get_utfString();

 Utf8String s1(s); //which above constructor should be called?

一种解决方法是:删除第二个构造函数的默认值。

此外,这些构造函数是复制构造函数,因此,explicit 没有多大意义。您将使用 explicit 来避免 implicit 从一种类型 X 到另一种类型 Y。在这种情况下,避免从 Utf8String const&Utf8String 的隐式转换是没有意义的,因为这样的转换不会真正引起问题(如果确实如此,那么问题可能出在代码的其他部分) .

【讨论】:

  • 感谢您的帮助。我不确定为什么显式在复制构造函数上没有意义。你能解释一下吗?
  • @Virus721:添加了对此的解释。
  • 好的。如果你愿意,我还会有另一个类似的问题。想象一下,我有一个方法Foo( const Utf8String & ) 和一个方法Foo( const char * )。由于 Utf8String 可以同时转换为 const Utf8String &const char *,所以我不会遇到这种方法 Foo 的问题吗?我也不能在方法上使用显式吗?谢谢。
  • @Virus721:试试看。探索。阅读更多关于explicit 的信息。查看更多示例。
【解决方案2】:

您的以下两个构造函数都可以用作复制构造函数:

explicit Utf8String( const Utf8String & sStr );
explicit Utf8String( const Utf8String & sStr, uint32_t nStart = 0, uint32_t nCpCount = UINT32_MAX );

它们中的每一个都匹配Utf8String( const Utf8String & sStr ) 签名。这是编译器不喜欢的。

你真的应该考虑一下你想使用两个构造函数中的哪一个作为复制构造函数。如果是第一个,则在第二个构造函数中删除 nStart 的默认值。如果是第二个,则完全删除第一个构造函数。

事实上,我假设你的第二个构造函数只接受一个子字符串,因此在没有nStartnCpCount 参数的情况下调用将完全像预期的复制构造函数一样工作。所以最简单的方法就是删除这对的第一个构造函数。

但是,这可能会导致一些(主要是性能)问题,具体取决于您对 Utf8String 的表示,因此这由您决定。

【讨论】:

  • 我将删除 nStart 的默认值以保留两个单独的构造函数,出于性能原因,正如您所猜测的那样。感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-03
相关资源
最近更新 更多