2013-12-15 3 views
0

я успешно запрограммирован однократно связанный список по следующей программе: Заголовочный файл:Как правильно использовать защищенные в односвязный список

#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; 
} 

основной .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; 
} 

Одна ошибка, например:

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| 

Аналогичная ошибка для других функций-членов, которые использовали ключ и следующий.

Эта программа работает очень хорошо. Однако после того, как я переместил 2 строки в node класс, int key; node *next; под protected, тогда он дает мне ошибку, такую ​​как «node :: key protected».

Во-первых, пожалуйста, не обвиняйте меня в том, что вы делаете что-то глупое: P. Я знаю, если бы я struct для узла, тогда жизнь будет намного проще. Я пытаюсь практиковать наследование и понимать защищенные. Вот почему.

По определению для защищенных членов можно получить производный класс, не так ли? Я не знаю, где я делаю это неправильно.

Надеюсь, вы можете мне помочь. Благодаря!

+0

Как насчет отображения строки, в которой происходит ошибка, и фактической ошибки компиляции, которую вы получаете? – greatwolf

+0

Кажется, вы пытаетесь установить 'key' и' next' извне класса, а не методы в классе. –

+0

@greatwolf, да, точная ошибка, указанная в компиляторе, - «SLL.h | 7 | ошибка:« int node :: key »защищен» – Cancan

ответ

1

Ключевое слово protected позволяет наследовательному классу видеть членов protected. Это означает, что экземпляры наследующего класса могут видеть защищенные члены сами по себе, а также защищенные члены других экземпляров того же наследующего класса. Он не расширяет этот доступ с помощью указателей на тип родительского класса, поскольку этот доступ небезопасен.

Давайте сделаем этот бетон. Рассмотрим следующий пример:

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. 
     } 
}; 

Ошибки в коде выглядят как второй случай. Так почему же второй случай незаконный, но третий случай ОК?

Второй случай является незаконным, поскольку компилятор не знает фактического типа объекта, на который указывает A*. Он может быть любым потомком A, и может даже не быть конвертируемым в B*. Следовательно, доступ, расширенный в соответствии с пунктом protected, не гарантированно является безопасным или значимым. Например, предположим, что вы имели

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

и вы прошли C* или D* в методе bad() выше. Не представляется разумным, что B должен иметь возможность видеть защищенные элементы, которые были выставлены C, так как C и B напрямую не связаны. То же самое справедливо и для D.

Но, в третьем случае, компилятор знает наверняка есть указатель на B или класс, производный от B, поэтому он знает, что доступ продлен protected ключевого слова является безопасным и значимым.Под этим я подразумеваю, что защищенные поля управляются таким образом, что B ожидает их управления. Фактически, без этого доступа вам было бы трудно записывать двоичные операторы с двумя экземплярами B

Имеют смысл?

В случае, если вы все еще не убеждены: Предположим, что я сделал два параллельных классов, оба, которые наследуют от 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 { }; 

Конечно, это надуманный пример, но несут с собой. Поскольку оба класса получают от node, вы можете пройти любой класс через node *. Итак, вы можете передать экземпляр negative_sll в normal_sll или наоборот.

Контроль доступа C++ не позволяет любому классу просматривать защищенные поля с помощью этого node *. И это хорошо, потому что negative_sll управляет ими иначе, чем normal_sll.

Но вы не можете передать экземпляр negative_sll через normal_sll* или наоборот. Итак, вы знаете, есть ли у вас normal_sll* внутри одного из методов normal_sll, вы знаете, что безопасно обращаться к защищенным членам.

Несомненно, это надуманный пример. Я уверен, что вы могли бы подумать о лучшем. Есть смысл, правда?

Теперь вы можете сделать B a friend от A и отменить этот контроль. Но, это позволило бы Bчастный членов A, полностью обходя protected концепции. Лучшим решением было бы переписать ваш код SLL, чтобы вы передали его методам SLL*, а не node*.

0

Прежде всего, я не вижу, почему вы хотите получить SLL от 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(); 
}; 

Насколько ваш вопрос - почему SLL не может получить доступ к Node «S защищенных членов - обеспокоен:

- ------- EDIT: Мое объяснение было просто неправильным ------------

+0

Создание 'SLL'' friend' обходит все элементы управления доступом, что в значительной степени делает 'protected' нерелевантным. –

+0

@JoeZ: Да, конечно, вы могли бы сделать их частными. Я просто хотел свести к минимуму изменения кода примера OP. Или я не понимаю вас? – MikeMB

+0

Это свести к минимуму изменения кода OP, но это не сделает код OP более правильным. Я считаю, что лучшим ответом для OP является изменение ссылок 'node *' на 'SLL * 'в реализации SLL. –

Смежные вопросы