我通过以下程序成功编写了单链表: 头文件是:
#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
#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|
使用密钥和下一个的其他成员函数的类似错误。
此程序现在运作良好。但是,在node
类int key; node *next;
下移动了protected
下的{2}行后,它会给我一些错误,例如“node :: key is protected”。
首先,请不要怪我做一些愚蠢的事情:P。我知道如果我struct
为节点,那么生活会更容易。我正在尝试继承并理解受保护。这就是原因。
根据定义,派生类可以访问受保护的成员,对吧?我不知道我做错了什么。
希望你能帮助我。谢谢!
答案 0 :(得分: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
派生的类,因此它知道{{1}扩展了访问权限} keyword是安全且有意义的。通过这种方式,我的意思是受保护的字段以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
,反之亦然。
C ++的访问控制阻止任何一个类通过normal_sll
查看受保护的字段。这很好,因为node *
管理它们的方式与negative_sll
不同。
但是,您无法通过normal_sll
传递negative_sll
的实例,反之亦然。因此,您知道如果normal_sll*
方法中有一个normal_sll*
,您就知道访问受保护成员是安全的。
当然,这是一个人为的例子。我相信你能想到更好的一个。但是有意义吗?
现在,您可以将normal_sll
设为B
friend
并覆盖此控件。但是,这会让A
看到B
的私有成员,完全绕过A
概念。更好的解决方案是重写protected
代码,以便将SLL
而不是SLL*
传递给其方法。
答案 1 :(得分:0)
首先,我没有看到,为什么你想从SLL
派生Node
,因为List不是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
的受保护成员 - 关注:
---------编辑:我的解释是错误的------------