2

我正在处理的任务有问题。我们正在编写一个在它自己的命名空间中定义的复数类。除了 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&)

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

4

1 回答 1

3

它模棱两可的原因是因为你有两个独立的功能。一个驻留在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所需的衍生工具一起使用。

于 2013-08-15T03:41:41.913 回答