为什么 cout 调用父运算符 << 而不是子运算符 <<

why is cout calling parent operator<< instead of child operator<<

我有 3 个 class,我希望每个都以不同的方式打印到终端,我现在有一个节点 class 表示 BDD 图中的一个顶点我正在尝试编写代码以在节点上执行逻辑操作。

节点 class 设置如下:

class Node {

    char name;

    public:
        Node() { name = '0'; }
        Node(char c) { name = c; }

        Node(const Node& n) { name = n.name; }

        friend ostream& operator<<(ostream& stream, const Node& n);
};

ostream& operator<<(ostream& stream, const Node& n) {
    return stream << "{ Node " << n.name << " }";
}

运算符 classes 是这样设置的:

class Operation {
    public:

    Node result;

    friend std::ostream& operator<<(std::ostream& stream, const Operation& op);

    Operation() {}

    Operation(const Operation& op) { cout << "Copying " << *this << endl; }

    virtual ~Operation() { cout << "Destroying " << *this << endl; }

    virtual Node compute() { 
        cout << "Computing " << *this << endl; 
        result = Node('1');
        return result; 
    }
};

std::ostream& operator<<(std::ostream& stream, const Operation& op) { 
    return stream << "Operation { Unspecified }"; 
}


class UnaryOperation : public Operation {
    public:

    Node arg1;

    UnaryOperation(const Node& arg1) { this->arg1 = arg1; }

    UnaryOperation(const UnaryOperation& op) : Operation::Operation(op) {
        arg1 = op.arg1;
    }

    virtual ~UnaryOperation() {}

    friend ostream& operator<<(ostream& stream, const UnaryOperation& op);
};

ostream& operator<<(ostream& stream, const UnaryOperation& op) {
    return stream << "Operation { arg1: " << op.arg1 << " }";
}


class BinaryOperation : public UnaryOperation {
    public:

    Node arg2;

    BinaryOperation(const Node& arg1, const Node& arg2) : UnaryOperation(arg1) { 
        this->arg2 = arg2; 
    }

    BinaryOperation(const BinaryOperation& op) : UnaryOperation::UnaryOperation(op) {
        arg2 = op.arg2;
    }

    virtual ~BinaryOperation() {}

    friend ostream& operator<<(ostream& stream, const BinaryOperation& op);
};

ostream& operator<<(ostream& stream, const BinaryOperation& op) {
    return stream << "Operation { arg1: " << op.arg1 << ", arg2: " << op.arg2;
}

出于调试原因,这些消息需要这样打印出来,但是当我 运行 这个

Node apply(Operation& op) {
    cout << "Performing apply operation on " << op << endl;
    op.compute();
    return op.result;
}


int main() {
    Node a('a'), b('b');
    UnaryOperation uop(a);
    BinaryOperation bop(a, b);
    cout << uop << endl;
    cout << bop << endl;
    apply(uop);
    apply(bop);
}

我明白了

Operation { arg1: { Node a } }
Operation { arg1: { Node a }, arg2: { Node b }
Performing apply operation on Operation { Unspecified }
Computing Operation { Unspecified }
Performing apply operation on Operation { Unspecified }
Computing Operation { Unspecified }
Destroying Operation { Unspecified }
Destroying Operation { Unspecified }

不用说,这对调试帮助不大

为什么会这样,我该如何解决?

友元函数不是虚函数。根据第二个参数的类型选择。

在这个函数中

Node apply(Operation& op) {
    cout << "Performing apply operation on " << op << endl;
    op.compute();
    return op.result;
}

参数的类型是Operation &。所以在这个语句中

cout << "Performing apply operation on " << op << endl;

为类型为 Operation & 的对象调用了友元函数。

您可以按照下面的演示程序所示的方式使友元函数 "virtual"。

#include <iostream>

class Operation 
{
public: 
    virtual ~Operation() = default;

private:    
    virtual std::ostream & out( std::ostream &os = std::cout ) const
    {
        return os << "This is an Operation"; 
    }

    friend std::ostream& operator <<( std::ostream &stream, const Operation &op ) 
    { 
        return op.out( stream ); 
    }
};

class UnaryOperation : public Operation 
{
    std::ostream & out( std::ostream &os = std::cout ) const override
    {
        return os << "This is an Unary Operation";
    }

    friend std::ostream& operator <<( std::ostream &stream, const UnaryOperation &op ) 
    { 
        return op.out( stream ); 
    }
};

class BinaryOperation : public UnaryOperation 
{
    std::ostream & out( std::ostream &os = std::cout ) const override
    {
        return os << "This is a Binary Operation";
    }

    friend std::ostream& operator <<( std::ostream& stream, const BinaryOperation &op ) 
    { 
        return op.out( stream ); 
    }
};

void f( const Operation &op )
{
    std::cout << op << '\n';
}

int main() 
{
    BinaryOperation bop;

    f( bop );

    return 0;
}

它的输出是

This is a Binary Operation