2017-08-02 62 views
0

我试图使用解引用操作符来打印新创建的节点。C++:无法访问节点值

我的主要功能

int main() 
{ 
    Insert(3); 
    return 0; 
} 

插入()函数

void Insert(int data) 
{ 
    Node *temp = new Node ; 
    temp -> data = data ; 
    temp -> next = NULL ; 

    cout << *temp ; 

} 

我的错误:

tp.cpp: In function ‘void Insert(int)’: 
tp.cpp:27:10: error: no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘Node’) 
    cout << *temp ; 
+1

标准库中没有对'节点'的'''重载。你还泄漏了'Node * temp = new Node;' – user4581301

+0

然后如何看到节点的值,然后我刚刚声明? 谢谢! –

+1

您将不得不编写自己的'<<'运算符来处理'Node'。查看Stream(Bitshift)运算符:https://stackoverflow.com/questions/4421706/what-are-the-basic-rules-and-idioms-for-operator-overloading – user4581301

回答

1

问题: C++提供对于用户定义的类型,我们必须编写自己的操作符。错误no match for ‘operator<<’说,编译器无法找到一个<<运营商反对声明cout << *temp ;

可能的解决方案:

  1. 像@ user4581301说,你可以根据<<write your own operatorNode类型。

  2. 您还可以用cout << temp->data ;cout << (*temp).data ;替代cout << *temp ;语句,因为temp是指向结构的指针。您可以在data.之前使用->,但使用*运算符对其进行了解引用后,可以使用->

0

任何运算符基本上是一个函数。 例如,对于您的Rational类加法运算符重载运算符+可以被表示为成员函数:

class Rational 
{ 
    private: 
    ... 
    ... 
    public: 
    ... 
    //Implicit arg "this" is Left Hand operand. 
    //Explicitly stated arg objRational is Right Hand operand. 
    Rational operator+(const Rational& objRational) const {...}; 
    ... 
}; 

请注意,该参数是由const这里,以确保我们不会意外地改变操作数本身,并且该函数还标记为const以确保我们不修改this对象。 Arg由ref传递,因为如果我们没有确定地修改它,就不需要复制,也不需要伤害ref。

以上在技术上是一个函数,所以你可以做这样的事情

Rational r1(3, 4), r2(22, 7); 
Rational r3 = r1.operator+(r2); //Really possible! Try it! 

它当时只是一个语法糖添加到C++语法允许同一呼叫

Rational r3 = r1 + r2;


您写下了

cout << *temp ;

其中,的(*temp)类型是节点,coutostream类的对象。

因此,编译器现在正在寻找一个重载操作符,其左操作数为ostream对象,右操作数为Node对象。

所以,这是写作好,类ostream的自身内部的某个地方,

class ostream : ... 
{ 
    ... 
    ... 
    //Here, the only one explicit arg is Node, 
    //which is Right Hand side operand. 
    //Since it is a member operator, 
    //implicit arg "this" will be, by default, the LH operand. 
    public ostream& oprtator<<(const Node& objNode){...} 
    ... 
} 

但是,我们没有这种可能性,因为我们没有在第一时间写类ostream的。当它被写入时,你的节点不存在!此外,它可能需要访问objNode的私有成员,这将不被允许用于不是Node类成员的函数。

如果我们试图把它作为类节点的成员,它可以访问节点的私有成员。但是现在operator<<的左侧操作数将需要是Node,这会破坏整个目的。

所以,我们所做的就是让它成为朋友功能。

class Node 
{ 
    ... 
    ... 
    public: 
    ... 
    //Since this is NOT a member, bot LH and RH operand need to be stated explicitelty 
    friend ostream& operator<< (ostream& out, const Node& objNode) { out << node.data; return out; } 
    ... 
}; 

这将创建一个operator<<已经离开操作的ostream和右侧操作数node,并能接入节点的私有成员,因为它是朋友。 (^_^)

为什么接受并返回引用ostream对象?

因为当你尝试链接调用时,你需要连续写入相同的对象。

考虑一个声明:cout << "First: " << objNode1 << ", Second: " << objNode2;

将评估为

(
    (
    (
     cout << "First: " //Innermost call 
    ) << objNode1  
) << ", Second: " 
)<< objNode2; 

从内到外,每一个电话,我们需要ostream对象传递给重载运营商拥有所有以前的插入,因此内部调用需要返回参考以修改(插入后)ostream对象返回。

希望它有帮助;快乐编码:)