Linked List and Class Inheritance

Good day,
I have been assigned a project about polymorphism. The idea is that there is a linked list with the node data type containing one of four classes. The classes are all child classes of a Task class. The idea then, is to have a list containing the different child classes, and to be able to display their data.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//ParentTask.h
//
  class ParentTask {

 public:
 ParentTask();	
	
 virtual void set_date(string date_input); 
 virtual void set_desc(string desc);
 virtual void set_type(char type_input);
 virtual void set_all_info(ParentTask* to_add);
 virtual Date get_date();
 virtual string get_desc()=0;
 virtual char get_type()=0;
 virtual string display1();
	
 protected:
 char type;
 Date due_date;
 string description;
	
};


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//ParentTask.cpp
#include "ParentTask.h"

ParentTask::ParentTask(){
		
}


void ParentTask::set_desc(string desc) {
	
	description = desc;
}


void ParentTask::set_type(char type_input) {
	
	type = type_input;	
}

string ParentTask::display1() {
	
	// ...
}



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//classes.h
#include "ParentTask.h"

struct node {
	ParentTask* task;
	node* prev;
	node* next;
};



 class GenericTask : public ParentTask {
 	
 public:
 void set_desc(string desc);
 void set_date(string date_input); 
 void set_type(char type_input);
 Date get_date();
 string get_desc();
 char get_type();
 string display1();
 	
 private:
 Date due_date;
 string description;
 char type;
 		
 };

class List_of_Tasks {
	
 public:
 List_of_Tasks();
 void add(GenericTask &to_add);
 void add(ParentTask *to_add);
 void display1();

 
 private:
 node* head;
 node* tail;	
		
};
 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
//classes.cpp
#include "classes.h"
void GenericTask::set_desc(string desc) {
	
	description = desc;
}

string GenericTask::get_desc() {
	
	return description;
}

void GenericTask::set_type(char type_input) {
	
	type = type_input;
}
char GenericTask::get_type() {
	
	return type;
}

void GenericTask::set_date(string date_input) {
	
		due_date.set_date(date_input);
}

Date GenericTask::get_date() {
	return due_date;
}

string GenericTask::display1() {
	
	string display = due_date.get_full();
	display+= " -  ";
	display+=description;
	return display;	
}

void List_of_Tasks::add(GenericTask &to_add) {
	ParentTask* p_t = &to_add;
	if(head == NULL) { 
		head = new node;
		head->task = p_t;
		head->next = NULL;
		head->prev = NULL;
		tail = head;
	}
	else {
		node* adder = new node;
		adder->task = &to_add;
		adder->next = NULL;
		tail->next = adder;
		adder->prev = tail;
		tail = adder;
		adder = NULL;
		delete adder;
	}
}

void List_of_Tasks::display1(){
  	int i = 1;
  	cout<<head->task->get_type()<<endl;
	node* display_node = new node;
	display_node = head;
	cout<<display_node->task->get_type()<<endl;
	if(head == NULL){
		cout<<"Nothing to display!"<<endl;
	}
	else {
		cout<<i<<".  "<<display_node->task->display1()<<endl;
		i++;
		while(display_node->next != NULL) {
			display_node = display_node->next;	
			cout<<i<<".  "<<display_node->task->display1()<<endl;
			i++;		
		}		
	}
	delete display_node;
}




And finally main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include "classes.h"



int main(){
	List_of_Tasks t_list;
	ParentTask *p_task;
	vector<string> Completed;
	
	string command = "";
		
	while(command != "exit"){
		cout<<"Main menu"<<endl;
		cin>>command;
		if(command == "add"){
			cout << "What type of task is this? [G: Generic, S: Shopping, E: Event, H: Homework]"<<endl;
			char task_input;
			cin>>task_input;
			if(task_input == 'G'){
				GenericTask g_task;
				g_task.set_type('G');
				cout<<"When is the task due? DD/MM/YYYY"<<endl;
				string input_date = "";
				cin>>input_date;
				g_task.set_date(input_date);
				cout<<"How would you describe this task?"<<endl;
				string task_description = "";
				cin.ignore();
				getline(cin, task_description);
				g_task.set_desc(task_description);				
				t_list.add(g_task);				
				cout<<"Task added successfully"<<endl;
				}

			}
		
		else if(command == "print"){
			t_list.display1();
		}
      }


My issue is the following :
The program compiles and the following occurs:
-I enter "add", then "G" and then the rest of the requested data.
-The task is added successfully. I had cout<< statements in the add() function to confirm the data is added properly. I used cout<<head->task->get_type()<<endl; to check for type, etc. The function from GenericTask would be called, which is what I want .
-I enter "print". In the print function, I cout<<head->task->get_type()<<endl; to check if the data is correct before outputting it. But this command would then call get_type() from ParentTask, which is a pure virtual function, and the program crashes. What am I doing wrong? How come in one function, get_type calls the get_type from a child class, but in another, it calls the Parent one

Last edited on
Hi,

A few things:

I don't think you should have a generic class as one of your task types. Generic was meant to be for the base class. I woud have called the base class Task.

With your file names, name them the same as the classes - try to avoid putting more than one class declaration is a file. So have 1 cpp file and 1 header file for each class.

Avoid using NULL, nullptr was invented to fix the problems that NULL causes.

I would have virtual for the derived functions in the class declaration. Also the override keyword.

One should also have a virtual destructor.

Avoid having protected data, it's just as bad as having public data.

Pas std::string by const reference:

1
2
3
4
void GenericTask::set_date(const std::string& date_input) {
	
		due_date.set_date(date_input);
}


Even better: use a member initialization list.

What is the point of the get and set type - you shouldn't need it for polymorphism.

For polymorphism to work a function needs to declared to receive a pointer to base class, but is sent a pointer to derived class. That way it will call the derived class function - which is usually what you want.

Your print function is deleting a node - is that what you want? Why does it create a new node?
Topic archived. No new replies allowed.