Rule of 5 help

Hi I'm having trouble understanding how to implement the rule of 5 being constructor, copy constructor, destructor, move constructor, copy assignment, and move assignment. I just need to use the rule of five for the Deck class. I just need a bit of guidance since I'm newer to programming and have been struggling figuring this out.

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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//Card Header
#pragma once
#include <string>
#include <vector>

using namespace std;

class Card
{

public:

	enum suitValue { Heart, Spade, Club, Diamond };
	enum faceValue {
		Ace, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten,
		Jack, Queen, King
	};

	vector<string> suitStrings = { "Heart", "Spade", "Club", "Diamond" };
	vector<string> faceStrings = { "Ace", "Two", "Three", "Four", "Five",
		"Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King" };

private:

	suitValue suit;
	faceValue face;

public:


	//getters
	suitValue getSuit() const;
	faceValue getFace() const;

	//constructor
	Card(faceValue value, suitValue suit);

	//annoying, but it's how it's done...
	friend ostream& operator<<(ostream& os, const Card& card);
}; 
//Card class
#include "Card.h"
#include <iostream>

Card::Card(faceValue face, suitValue suit)
{
	this->suit = suit;
	this->face = face;
}

Card::suitValue Card::getSuit() const
{
	return suit;
}

Card::faceValue Card::getFace() const
{
	return face;
}


//output
ostream& operator<<(ostream& os, const Card& card)
{
	os << "This is the " << card.faceStrings.at(card.getFace()) << " of "
		<< card.suitStrings.at(card.getSuit()) << "s";
	return os;
}
//Deck Header
#pragma once

#include "Card.h"
#include <vector>

class Deck
{
private:
	vector<Card*> cards;
	const int NUM_SUITS = 4;
	const int NUM_FACES = 13;

public:
	//constructor
	Deck();


	//destructor
	~Deck();

	//printer
	void printDeck();
}; 
//Deck Class
#include "Deck.h"
#include <iostream>

using namespace std;

Deck::Deck()
{
	for (int i = 0; i < NUM_FACES; i++)
	{
		for (int j = 0; j < NUM_SUITS; j++)
		{
			Card* card = new Card((Card::faceValue) i, (Card::suitValue) j);	//casting i and j to appropriate enum... eew...
			cards.push_back(card);
		}
	}
	cout << "Constructor is working \n";
}
Deck::Deck(const Deck& obj)
{
	cards.clear;
	for (int i = 0; i < cards.size - 1; i++)
	{
		cards.push_back(obj.cards[i]);
	}
	cout << "Copy Constructor is working \n";
}

Deck::~Deck()
{
	//leaving this with its default behaviour is incorrect - why?
	for (Card* c : cards)
	{
		delete c;
	}
}

void Deck::printDeck()
{
	cout << "Printing the Deck of Cards:\n";
	for (Card* c : cards)
	{
		cout << *c << "\n";
	}
}
Why are you using a vector<Card*> in your Deck class? If you used a normal, non-pointer, instance you wouldn't need to worry about the "Rule of 5" since the default copy, move, destructor, assignment operator would be sufficient.

Also be careful:
1
2
3
Deck::Deck(const Deck& obj)
{
	cards.clear;

If your cards vector actually contained any elements you would likely have a memory leak here.

Line 78: Why are you using a vector of Card * here? This is going to cause problems.

Consider your copy constructor. Lets assume you have Deck A. Now you create Deck B(A).
You copy the Card * pointers from Deck A to Deck B. Now both Decks point to the same memory for each Card. Now you destruct Deck A. This releases the memory for the Cards that Deck A points to. The memory for the Cards in Deck B is now invalid.

Simply make your Deck: vector<Card> and you don't have to worry about improper use of pointers.




Topic archived. No new replies allowed.