简体   繁体   English

如何正确使用单链表中的受保护

[英]How to properly use protected in singly linked list

I've successfully programmed a singly linked list by the following program: The header file is: 我已经通过以下程序成功编写了一个单链表:头文件是:

#ifndef SLL_H_
#define SLL_H_

#include <iostream>
class node {
    protected:

    public:
        int key;
        node *next;
        node();
        ~node();
};

class SLL : public node{
    private:
        node *Head = NULL;
        int SLL_SIZE = 0;
    public:
        //Constructor
        SLL();
        //SLL(int n);
        //Destructor
        ~SLL();
        //Modifiers
        void Push_Front(int a);
        void Push_Back(SLL A,int b);
        void Traverse();
        //Access function
        int SLL_size();
        int Get(node* p);
        //Iterator
        node* Begin();
        node* End();
        //void Search(int a);

};

#endif

SLL.cpp 文件库

#include "SLL.h"
#include <iostream>

using namespace std;

node::node(){
    cout << "Empty constructor of node is being called;" << endl;
}

node::~node(){
    cout << "Empty destructor of node is being called;" << endl;
}

SLL::SLL():node(){
    cout << "Empty constructor of SLL is being called;" << endl;
}

SLL::~SLL(){
    cout << "Empty destructor of SLL is being called." << endl;
}

//Insert element at the front of the list
void SLL::Push_Front(int k){
    node *temp = new node [1];
    temp->key = k;
    temp->next = Head;
    Head = temp;
    SLL_SIZE = SLL_SIZE + 1;
}

//Insert element at the end of the list
void SLL::Push_Back(SLL A, int m){
    node *temp1 = A.End();
    node *temp2 = new node [1];
    temp2->key = m;
    temp1->next = temp2;
    temp2->next = NULL;
    SLL_SIZE = SLL_SIZE + 1;
}

//Insert element at a given position

//Return the number of elements in the linked list
int SLL::SLL_size(){
    return SLL_SIZE;
}

//Traverse the list (print the list)
void SLL::Traverse(){
    node *temp;
    temp = Head;
    while(temp!=NULL){
        cout << temp->key << " ";
        temp = temp->next;
    }
    cout << endl;
}

//Get key given pionter
int SLL::Get(node* pt){
    if(pt!=NULL){
        node* temp = pt;
        return temp->key;
    }
    else {
        cout << "Null pointer points to nowhere!" << endl;
        return 0;
    }
}

//Return the pointer at the beginning of the list
node* SLL::Begin(){
    return Head;
}

//Return the pointer at the end of the list
node* SLL::End(){
    node* temp = Head;
    while(temp->next!=NULL){
        temp = temp->next;
    }
    return temp;
}

main.cpp main.cpp

#include <iostream>
#include "SLL.h"

using namespace std;

int main()
{
    SLL A;
    A.Push_Front(1);
    A.Push_Front(2);
    A.Push_Front(5);
    A.Push_Front(6);
    A.Push_Back(A,3);
    A.Traverse();
    cout << A.SLL_size() << endl;
    cout << A.Get(A.Begin()) << endl;
    cout << A.Get(A.End()) << endl;
    return 0;
}

One error is, for example : 一个错误是,例如:

SLL.h||In member function 'void SLL::Push_Front(int)':|
SLL.h|7|error: 'int node::key' is protected|
SLL.cpp|25|error: within this context|
SLL.h|8|error: 'node* node::next' is protected|
SLL.cpp|26|error: within this context|
SLL.h||In member function 'void SLL::Push_Back(SLL, int)':|
SLL.h|7|error: 'int node::key' is protected|
SLL.cpp|35|error: within this context|
SLL.h|8|error: 'node* node::next' is protected|
LL.cpp|36|error: within this context|
SLL.h|8|error: 'node* node::next' is protected|
SLL.cpp|37|error: within this context|

Similar error for the other member functions that employed key and next. 使用key和next的其他成员函数的错误类似。

This program works very well now. 该程序现在运行良好。 However, after I moved the 2 lines in node class, int key; node *next; 但是,在移动node类中的两行后,输入int key; node *next; int key; node *next; under protected , then it gives me error such as "node::key is protected". protected之下,那么它给我错误,例如“ node :: key is protected”。

First, please don't blame me for doing something stupid :P . 首先,请不要怪我做愚蠢的事情:P。 I know if I struct for the node then life will be much easier. 我知道如果我为节点struct ,那么生活会容易得多。 I am trying to practice inheritance and to understand protected. 我正在尝试练习继承并了解保护。 That's why. 这就是为什么。

By definition, protected members can be accessed by derived class, right? 根据定义,受保护的成员可以通过派生类访问,对吗? I don't know where I am doing it wrong. 我不知道我在哪里做错了。

Hope you can help me out. 希望你能帮助我。 Thanks! 谢谢!

The protected keyword allows an inheriting class to see the protected members. protected关键字允许继承的类查看protected成员。 That means instances of the inheriting class can see the protected members of themselves, as well as the protected members of other instances of that same inheriting class. 这意味着继承类的实例可以看到自身的受保护成员,以及同一继承类的其他实例的受保护成员。 It does not extend this access through pointers to the parent class type, because that access isn't safe. 它不会通过指向父类类型的指针来扩展此访问,因为该访问并不安全。

Let's make that concrete. 让我们具体化。 Consider the following example: 考虑以下示例:

class A
{
    protected:
        int a_int;
};

class B : public A
{
    public:

        int good()
        {
            return a_int;  // OK:  Protected member of this instance
        }

        int bad( A *a_ptr )
        {
            return a_ptr->a_int; // BAD:  Can't access the protected member
                                 //       through a pointer to the parent class type.
        }

        int also_good( B *b_ptr )
        {
            return b_ptr->a_int; // OK:  Pointer to the same class type as this
                                 //      class is safe.
        }
};

The errors in your code look like the second case. 您的代码中的错误看起来像第二种情况。 So why is the second case illegal, but third case OK? 那么为什么第二种情况是非法的,而第三种情况却可以呢?

The second case is illegal because the compiler doesn't know the actual type of object the A* points to. 第二种情况是非法的,因为编译器不知道A*指向的对象的实际类型。 It could be any descendent of A , and may not even be convertible to B* . 它可以是A 任何后代,甚至不能转换为B* Therefore, the access extended by the protected clause isn't guaranteed to be safe or meaningful. 因此,不能保证protected子句扩展的访问是安全或有意义的。 For example, suppose you had 例如,假设您有

class C : public A { ... };
class D : public C { ... };

and you passed a C* or a D* into method bad() above. 并且您将C*D*传递到上述方法bad() It doesn't seem reasonable that B should be able to see the protected members that were exposed to C , since C and B aren't directly related. B应该能够看到暴露给C的受保护成员似乎是不合理的,因为CB没有直接关系。 The same holds true for D . D也是如此。

But, in the third case, the compiler knows for certain it has a pointer to a B or a class derived from B , so it knows that the access extended by the protected keyword is safe and meaningful. 但是,在第三种情况下,编译器肯定会知道它有一个指向B或从B派生的类的指针,因此它知道由protected关键字扩展的访问是安全且有意义的。 By that, I mean that the protected fields are managed in the way B expects them to be managed. 这样,我的意思是按照B期望对受保护字段的管理方式进行管理。 In fact, without that access, you would have a hard time writing binary operators involving two instances of B 实际上,如果没有这种访问权限,您将很难编写涉及两个B实例的二进制运算符

Make sense? 说得通?

In case you're still not convinced: Suppose I made two parallel classes, both which inherit from node : 如果您仍然不相信:假设我做了两个并行的类,它们都继承自node

// plain singly linked list
class normal_sll : public node { };

// singly linked list that stores all of its elements negated
class negative_sll : public node { };

Sure, it's a contrived example, but bear with me. 当然,这是一个人为的例子,但请忍受。 Because both classes derive from node , you could pass either class through a node * . 因为这两个类都是从node派生的,所以您可以通过node *传递这两个类。 So, you could pass an instance of negative_sll to normal_sll or vice versa. 因此,您可以将negative_sll的实例传递给normal_sll ,反之亦然。

C++'s access control prevents either class from looking at the protected fields through that node * , though. 但是,C ++的访问控制可防止任何一个类通过该node *查看受保护的字段。 And that's good, because negative_sll manages them differently than normal_sll . 那样很好,因为negative_sllnormal_sll管理方式不同。

But, you can't pass an instance of negative_sll through a normal_sll* or vice versa. 但是,您不能通过normal_sll*传递negative_sll的实例,反之亦然。 So, you know if you have a normal_sll* inside one of normal_sll 's methods, you know it's safe to access the protected members. 因此,您知道在normal_sll的方法之一中是否具有normal_sll* ,就可以安全地访问受保护的成员。

Sure, it's a contrived example. 当然,这是一个人为的例子。 I'm sure you could think of a better one. 我相信您会想到更好的选择。 Make sense, though? 有道理吗?

Now you could make B a friend of A and override this control. 现在,您可以将B friend Afriend ,并覆盖此控件。 But, this would let B see the private members of A , totally bypassing the protected concept. 但是,这将使B看到A私有成员,而完全绕开了protected概念。 A better solution would be to rewrite your SLL code so that you pass SLL* , not node* to its methods. 更好的解决方案是重写SLL代码,以便您将SLL*而不是node*传递给其方法。

First of all, I don't see, why you want to derive SLL from Node at all, as a List is not a specialization of a Node. 首先,我不明白为什么您要从Node派生SLL ,因为List不是Node的特化。 What you probably want to do instead is to make SLL a friend of Node: 您可能要做的是使SLL成为Node的朋友:

class node {
protected:
    int key;
    node *next;
public:
    friend SLL; //This allows SLL to access node's private and protected members

    node();
    ~node();
};

As far as your question - why SLL can't access Node 's protected members - is concerned: 就您的问题-为什么SLL无法访问Node的受保护成员-而言:

--------- EDIT: My explanation was just wrong ------------ ---------编辑:我的解释是错误的------------

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM