Using Polymorphism

The code below is suppose to compile and execute. However, when compiling, an error C2280 is generated by line 94 as it is attempting to reference a deleted function.

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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// Team Builder
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <memory>
using namespace std;

#define interface struct
interface IWork
{
	virtual const char* get_name() = 0;
	virtual const char* get_position() = 0;
	virtual void do_work() = 0;
};

interface IManage
{
	virtual const vector <unique_ptr<IWork>>& get_team() = 0;
	virtual void manage_team() = 0;
};

interface IDevelop
{
	virtual void write_code() = 0;
};

// helper class for worker
class worker : public IWork
{
	string name;
	string position;
public:
	worker() = delete;
	worker(const char *n, const char *p) : name(n), position(p) {}
	virtual ~worker() {}
	virtual const char* get_name() override
	{
		return this->name.c_str();
	}
	virtual const char* get_position() override
	{
		return this->position.c_str();
	}
	virtual void do_work() override
	{
		cout << "works" << endl;
	}
};

// helper class for manager
class manager : public worker, public IManage
{
	vector<unique_ptr<IWork>> team;
public:
	manager() = delete;
	manager(const char *n, const char* p) : worker(n, p) {}
	const vector<unique_ptr<IWork>>& get_team()
	{
		return team;
	}
	virtual void manage_team() override
	{
		cout << "manage a team" << endl;
	}
	void add_team_member(IWork* worker)
	{
		team.push_back(unique_ptr<IWork>(worker)); 
	}
	virtual void do_work() override
	{
		this->manage_team();
	}
};

class project_manager : public manager
{
public:
	project_manager() = delete;
	project_manager(const char *n) : manager(n, "Project Manager") {}
	virtual void manage_team() override
	{
		cout << "manages team of developers" << endl;
	}
};

void print_team(IWork *mgr)
{
	cout << mgr->get_name() << " is " << mgr->get_position() << " and ";
	IManage *manager = dynamic_cast<IManage*>(mgr);
	if (manager != nullptr)
	{
		cout << "manages a team of: " << endl;
		for (auto team_member : manager->get_team())
		{
			cout << team_member->get_name() << " " << team_member->get_position() << endl;
		}
	}
	else
	{
		cout << "is not a manager" << endl;
	}
}

int main(int argc, const char *argv[])
{
	project_manager pm("Agnes");
	pm.add_team_member(new worker("Bill", "Developer"));
	pm.add_team_member(new worker("Chris", "Developer"));
	pm.add_team_member(new worker("Dave", "Developer"));
	pm.add_team_member(new worker("Edith", "DBA"));

	print_team(&pm);
	return 0;
}
As you surmise, the problem is on line 94. The ranged for loop there is trying to create a copy of each element in the vector of unique pointers. In effect, trying to create a copy of a unique pointer. This is forbidden.

However, you don't need a copy, do you? You can just use the actual unique pointer in the vector. You can tell the range based for loop that you want to work with a reference to the unique pointer, rather than a copy of it:

1
2
3
4
	for (const auto& team_member : manager->get_team())
		{
			cout << team_member->get_name() << " " << team_member->get_position() << endl;
		}

In this code, team_member is a const reference to the unique pointer. All good.

This is a post I have found useful in the past: https://blog.petrzemek.net/2016/08/17/auto-type-deduction-in-range-based-for-loops/
Last edited on
Thank you very much for the solution, Repeater. Appreciate the explanation.
i wanna ask, what's this define do?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#define interface struct
interface IWork
{
	virtual const char* get_name() = 0;
	virtual const char* get_position() = 0;
	virtual void do_work() = 0;
};

interface IManage
{
	virtual const vector <unique_ptr<IWork>>& get_team() = 0;
	virtual void manage_team() = 0;
};

interface IDevelop
{
	virtual void write_code() = 0;
};
Last edited on
#define interface struct tells the preprocessor to find every instance of the word interface and replace it with the word struct, before the compiler gets to look at the code. So the compiler sees this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct IWork
{
	virtual const char* get_name() = 0;
	virtual const char* get_position() = 0;
	virtual void do_work() = 0;
};

struct IManage
{
	virtual const vector <unique_ptr<IWork>>& get_team() = 0;
	virtual void manage_team() = 0;
};

struct IDevelop
{
	virtual void write_code() = 0;
};


What you've got here is someone writing their own programming language using the preprocessor. I'm guessing that someone wanted to mark out their abstract classes with the word "interface" in the code. I have to say that if I saw this in a code review in code that a team had to work on (obviously individuals can do whatever they like with their code!), I'd send it back because

1) The word "interface" could well come up in other code, maybe in the future, and one day someone else's code will break because they used the word "interface" for something else entirely (such as part of a variable name, or a function call, or anything really). This is a little landmine that will blow up in someone else's face in the future, which is very bad manners.

2) The convention of using "I" on the class name is already a widely recognised way to suggest that you intend this class to be abstract, and contain only some functions; no need to create your own programming language using the preprocessor.
#define interface struct tells the preprocessor to find every instance of the word interface and replace it with the word struct, before the compiler gets to look at the code. So the compiler sees this:...


omg, so sorry, my mistake... didn't notice it...
Let me state the author's reason for Interfaces.

Basically, an interface is a class that has no functionality and only applies to virtual functions. The purpose of an interface is to define behavior. A concrete class that derives from an interface must provide an implementation of all of the methods of the interface, and hence, this makes the interface a kind of a contract. ... Interface programming decouples behavior from implementation. Client code is only interested in the actual class that provides the interface.
Topic archived. No new replies allowed.