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
#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.
This program works very well now. However, after I moved the 2 lines in node
class, int key; node *next;
under protected
, then it gives me error such as "node::key is protected".
First, please don't blame me for doing something stupid :P . I know if I struct
for the node then life will be much easier. 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 theprotected
members. 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:
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. It could be any descendent ofA
, and may not even be convertible toB*
. Therefore, the access extended by theprotected
clause isn't guaranteed to be safe or meaningful. For example, suppose you hadand you passed a
C*
or aD*
into methodbad()
above. It doesn't seem reasonable thatB
should be able to see the protected members that were exposed toC
, sinceC
andB
aren't directly related. The same holds true forD
.But, in the third case, the compiler knows for certain it has a pointer to a
B
or a class derived fromB
, so it knows that the access extended by theprotected
keyword is safe and meaningful. By that, I mean that the protected fields are managed in the wayB
expects them to be managed. In fact, without that access, you would have a hard time writing binary operators involving two instances ofB
Make sense?
In case you're still not convinced: Suppose I made two parallel classes, both which inherit from
node
:Sure, it's a contrived example, but bear with me. Because both classes derive from
node
, you could pass either class through anode *
. So, you could pass an instance ofnegative_sll
tonormal_sll
or vice versa.C++'s access control prevents either class from looking at the protected fields through that
node *
, though. And that's good, becausenegative_sll
manages them differently thannormal_sll
.But, you can't pass an instance of
negative_sll
through anormal_sll*
or vice versa. So, you know if you have anormal_sll*
inside one ofnormal_sll
's methods, you know it's safe to access the protected members.Sure, it's a contrived example. I'm sure you could think of a better one. Make sense, though?
Now you could make
B
afriend
ofA
and override this control. But, this would letB
see the private members ofA
, totally bypassing theprotected
concept. A better solution would be to rewrite yourSLL
code so that you passSLL*
, notnode*
to its methods.First of all, I don't see, why you want to derive
SLL
fromNode
at all, as a List is not a specialization of a Node. What you probably want to do instead is to make SLL a friend of Node:As far as your question - why
SLL
can't accessNode
's protected members - is concerned:--------- EDIT: My explanation was just wrong ------------