【问题标题】:C++ Ambiguous over for 'operator>>' in 'std::cin >>''std :: cin >>'中'operator>>'的C ++模棱两可
【发布时间】:2013-08-17 05:49:09
【问题描述】:

我正在处理的任务有问题。我们正在编写一个在它自己的命名空间中定义的复数类。除了 istream 和 ostream 上的重载之外,我一切正常。让我发布一些我的代码:

namespace maths {

    class complex_number{
    public:

        // lots of functions and two variables

        friend std::istream& operator >>(std::istream &in, maths::complex_number &input);

    }
}

std::istream& operator >>(std::istream &in, maths::complex_number &input)
{
   std::cout << "Please enter the real part of the number > ";
   in >> input.a;
   std::cout << "Please enter the imaginary part of the number > ";
   in >> input.b;

   return in;
}

int main(int argc, char **argv)
{
   maths::complex_number b;
   std::cin >> b;

   return 0;
}

我得到的错误如下:

com.cpp: In function ‘int main(int, char**)’:
com.cpp:159:16: error: ambiguous overload for ‘operator>>’ in ‘std::cin >> b’
com.cpp:159:16: note: candidates are:
com.cpp:131:15: note: std::istream& operator>>(std::istream&, maths::complex_number&)
com.cpp:37:26: note: std::istream& maths::operator>>(std::istream&, maths::complex_number&)

我在这里花了一些时间阅读论坛,偶然发现了一个关于名称隐藏的答案,但我似乎无法让它与我的代码一起使用。非常感谢任何帮助!

【问题讨论】:

  • 定义应该真正进入命名空间imo。那么这两个签名都不需要maths:: 部分,它应该仍然可以工作。
  • 您能详细说明一下吗?您的意思是不要将它们声明为友元函数(因为我试图访问的值是公开的,所以我可以这样做)?还是以不同的方式进行?
  • 如果它不需要访问私人部分,那么是的,它绝对不应该是一个朋友功能。我的意思是将实际重载放入您的maths 命名空间,因为它与类一起使用。 ADL 会找到它。但是,您的观点意味着类内不需要声明。

标签: c++ class namespaces overloading istream


【解决方案1】:

之所以模棱两可,是因为您有两个独立的函数。一个位于maths 命名空间中,并由类内标记为friend 的那个声明。这个可以通过 Argument Dependent Lookup 找到。您在命名空间之外还有一个完整的定义。这两者同样有效。

首先,它不访问类的任何私有成员,因此不需要friend 声明。只是不要让它成为朋友,因为这只会伤害封装。

其次,我建议将定义移至maths 命名空间,因为它与正在运行的类一起属于那里。如前所述,ADL 仍然会找到它,因为第二个参数是该命名空间中的类型,因此搜索命名空间并找到重载。

总而言之,你应该得到这个:

namespace maths {

    class complex_number{
    public:
        // lots of functions and two variables
    };

    std::istream& operator >>(std::istream &in, maths::complex_number &input)
    {
       std::cout << "Please enter the real part of the number > ";
       in >> input.a;
       std::cout << "Please enter the imaginary part of the number > ";
       in >> input.b;

       return in;
    }
}

int main(int argc, char **argv)
{
   maths::complex_number b;
   std::cin >> b; //operator>> found by ADL

   return 0;
}

最后一点是重载本身。 Input 真的不应该提示输入,它应该只是读取它们。这样,您就可以将它与键盘、文件或任何其他需要的 std::istream 派生对象一起使用。

【讨论】:

  • 这成功了!因此,将重载函数移到类之外,但仍在命名空间内。现在看起来很明显,我认为只是看了太久。也感谢您的其他建议。
猜你喜欢
  • 2012-07-14
  • 1970-01-01
  • 1970-01-01
  • 2012-12-08
  • 1970-01-01
  • 2020-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多