c++ - 如何显式调用好友流操作符?

标签 c++ gcc

<分区>

考虑到这个片段,正如预期的那样,当调用流运算符而不指定命名空间时(通过像 1 一样调用流运算符),gcc 无法找到在 NA::operator<< 和 NB::operator<< 之间选择哪个符号。可以明确地调用 NB::operator<<(如 2)。这运行并具有预期的行为。但是当尝试对 friend stream operator(如 3)执行相同操作时会出现构建错误,告知 operator<< 不是 NA 的成员。为什么? NA::operator<< 似乎是在 case 1)...

#include <iostream>
#include <vector>

#include <fstream>

namespace NA {
    class A {
        friend inline std::ostream & operator<<(std::ostream & s, const A & object) {
            std::cout << "NA::operator<<" << std::endl;
            return s;
        }
    };
}

namespace NB {
    std::ostream & operator<<(std::ostream & s, const NA::A & object) {
        std::cout << "NB::operator<<" << std::endl;
        return s;
    }
    void func(const NA::A* a);
}

void NB::func(const NA::A* a) {
    std::ofstream ofs;
    //1)
    //ofs << *a; //build error:
    //error: ambiguous overload for 'operator<<' (operand types are 'std::ofstream' {aka 'std::basic_ofstream<char>'} and 'const NA::A')
    //2)
    //NB::operator<<(ofs, *a); //runs and displays NB::operator<<
    //3)
    NA::operator<<(ofs, *a); //build error:
    //error: 'operator<<' is not a member of 'NA'
}

int main()
{
    NA::A obj_a;
    NB::func(&obj_a);
}

我的问题是,如何明确调用 NA::operator<< ?

最佳答案

这个cas有点奇怪。

对于这段代码:

ofs << *a;

编译器明确指出两者之间存在歧义:

main.cpp:16:20: note: candidate: 'std::ostream& NB::operator<<(std::ostream&, const NA::A&)'
     std::ostream & operator<<(std::ostream & s, const NA::A & object) {
                    ^~~~~~~~

main.cpp:8:38: note: candidate: 'std::ostream& NA::operator<<(std::ostream&, const NA::A&)'
         friend inline std::ostream & operator<<(std::ostream & s, const A & object) {
                                      ^~~~~~~~

但是当通过

显式调用运算符时
NA::operator<<(ofs, *a);

编译器没有找到它:

main.cpp:39:17: error: 'operator<<' is not a member of 'NA'
    NA::operator<<(ofs, *a);
                ^~

我发现的唯一解决方法是在 namespace NA 中声明一个函数,它将调用运算符,然后编译器能够选择好的函数:

namespace NA {
    void print_it(std::ofstream & os, const A & a)
    {
        os << a;
    }
}

好的,感谢@Passer By的评论,我明白了

声明函数 friend 不会被编译器查看,添加方法的前向声明,如:

namespace NA {
    class A;
    std::ostream & operator<<(std::ostream & s, const A & object);
}

允许编译器找到声明,因此

NA::operator<<(ofs, *a);

将由编译器解析。

关于c++ - 如何显式调用好友流操作符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51613113/

相关文章:

c++ - 在基于 Makefile 的解决方案中使用 Visual Studio 调试器

c - GCC 不提示未初始化的变量

c++ - Scons 选择哪个版本的g++ |无法识别的命令行选项 "-std=c++11"

c - 为什么要使用三元运算符而不为 "true"条件赋值 (x = x ? : 1)

c++ - 来自 TinyXML++ 的奇怪行为

c++ - 插入通用容器不起作用

c++ - 弃用的函数和 fseek()

c - 奇怪的 'asm' 操作数有不可能的约束错误

c - C 的结构中的 "Inheritance"?

c++ - 花 : How do I create a tuple of types from a variant?