In: Computer Science
Programming Exercise
Implement the following class design:
class Tune
{
private:
string title;
public:
Tune();
Tune( const string &n );
const string & get_title() const;
};
class Music_collection
{
private:
int number; // the number of tunes actually in the collection
int max; // the number of tunes the collection will ever be able to hold
Tune *collection; // a dynamic array of Tunes: "Music_collection has-many Tunes"
public:
// default value of max is a conservative 100
Music_collection();
// sets max to n
Music_collection( int n );
// overloaded copy constructor
Music_collection( const Music_collection &m);
// returns true if add was successful,
// returns false if not enough room to add
bool add_tune( const Tune &t );
// sets the Tune at position index in collection to t,
// returns true if index < number
bool set_tune( int index, const Tune &t );
// overloaded assignment operator
Music_collection & operator=( const Music_collection &m );
// Destructor
~Music_collection();
// overloaded stream insertion operator
// outputs the title of each Tune in the collection on a separate line
friend ostream & operator<<( ostream &out, const Music_collection &m );
};
Testing
Now let’s give your code a test run.
You should build a test harness that uses the following pseudo-code:
main()
{
//create a few Tune objects to use later on;
Music_collection A;
//add a few tunes to A;
Music_collection B(A);
//change a Tune in B using set_tune function;
Music_collection C;
C = B;
//add a Tune to B;
//change a Tune in C using set_tune function;
//print A,B,C;
}
After you test your work, comment out the assignment operator and copy constructor in .h and .cpp files of your Music_collection class implementation. re-compile and run your code. Compare the results with the previous run. (Ignore seg. fault and memory corruption errors, on terminal just check the lines right after you call your binary executable, i.e a.out)
Pay careful attention to the "boundary" or special cases: e.g. what happens if you try to assign an object to itself? (When could this happen?)
Remember to free the memory of the left-hand-side object of the assignment operator.
Remember to make deep copies, not shallow copies. (Make sure you can explain exactly what this means!)
What to submit
submit the following files (case sensitive):
music_collection.h (this file also contains Tune class)
music_collection.cpp
main.cpp
Programming language: C++
Requirement: Please tightly follow up the requirement as demonstrated above.
1. comment out the assignment operator and copy constructor in .h and .cpp files of your Music_collection class implementation. Re-complie and run your code
2. complete Music_collection.cpp file
3. provide illustration/comments with output result
#include<bits/stdc++.h>
using namespace std;
class Tune {
private:
string title;
public:
Tune();
Tune( const string &n ) {
title = n;
}
const string & get_title() const {
return title;
}
};
class Music_collection {
private:
int number; // the number of tunes actually in the collection
int max; // the number of tunes the collection will ever be able to hold
Tune *collection; // a dynamic array of Tunes: "Music_collection has-many Tunes"
public:
// default value of max is a conservative 100
Music_collection() {
number = 0;
max = 100;
collection = (Tune*)malloc(max * (sizeof(Tune)));
}
// sets max to n
Music_collection( int n ) {
number = 0;
max = n;
collection = (Tune*)malloc(max * (sizeof(Tune)));
}
// overloaded copy constructor
Music_collection( const Music_collection &m) {
max = m.max;
number = m.number;
collection = (Tune*)malloc(max * (sizeof(Tune)));
for (int i = 0; i < number; ++i) {
collection[i] = m.collection[i];
}
}
// returns true if add was successful,
// returns false if not enough room to add
bool add_tune( const Tune &t ) {
if (number == max) {
return false;
}
collection[number] = t;
number++;
}
// sets the Tune at position index in collection to t,
// returns true if index < number
bool set_tune( int index, const Tune &t ) {
if (index < number) {
collection[index] = t;
return true;
}
return false;
}
// overloaded assignment operator
Music_collection & operator=( const Music_collection &m ) {
max = m.max;
number = m.number;
collection = (Tune*)malloc(max * (sizeof(Tune)));
for (int i = 0; i < number; ++i) {
collection[i] = m.collection[i];
}
return *this;
}
// Destructor
// ~Music_collection();
// overloaded stream insertion operator
// outputs the title of each Tune in the collection on a separate line
friend ostream & operator<<( ostream &out, const Music_collection &m );
};
std::ostream& operator<<(std::ostream& out, const Music_collection &m)
{
for (int i = 0; i < m.number; ++i) {
cout << m.collection[i].get_title() <<",";
}
cout<<endl;
return out;
}
// Testing
// Now let’s give your code a test run.
// You should build a test harness that uses the following pseudo - code:
main()
{
//create a few Tune objects to use later on;
Music_collection A;
//add a few tunes to A;
Tune a("California");
Tune b("Betles");
Tune c("Dance");
Tune d("Flying");
A.add_tune(a);
A.add_tune(b);
A.add_tune(c);
A.add_tune(d);
Music_collection B(A);
//change a Tune in B using set_tune function;
B.set_tune(2,Tune("Kamli"));
Music_collection C;
C = B;
//add a Tune to B;
B.add_tune(Tune("Zamana"));
//change a Tune in C using set_tune function;
C.set_tune(3,Tune("Loward"));
cout<<A;
cout<<B;
cout<<C;
//print A,B,C;
}
OUTPUT: