Reputation: 152
I want to write a copy constructor for the Plane
class.
class Widget{ };
class Button: public Widget{};
class Label: public Widget {};
class Plane {
vector<Widget*>vec;
public:
void Add (Widget* w) {
vec.push_back(w);
}
// need to implement copy constructor for this class???
//Plane (const Plane &obj) ???
~Plane() {
for (auto w: vec) {
delete w;
}
}
};
int main () {
Plane p1;
p1.Add(new Button);
p1.Add(new Label);
Plane p2(p1);
return 0;
}
Need your help to write a copy constructor for class Plane
. Do I also need to change something in the Widget class
as well? I want to have a deep copy and that's why a copy constructor is required here. I tried to write the copy constructor by myself but failed.
Upvotes: 2
Views: 178
Reputation: 1504
I don't know why you decided to use raw pointers instead of unique_ptr
s.
unique_ptr
s have RAII functionality, meaning when going out of scope they automatically destroy, along with the pointer, the resource pointed-to.
With raw pointers instead, you are required to delete
them manually. In addition, if you employ them as data members in a custom class, you are also required to define your own copy
&move
constructors and assignment operators.
A clone()
method (which in Java I hear is infamous, much less so in C++) would allow you to perform deep copy of the vector<Widget*>
as you require for your code.
The program should work if modified as below:
#include <iostream>
#include <vector>
#include <utility>
#include <stdexcept>
using std::cout;
using std::vector;
using std::move;
using std::exception;
using std::logic_error;
class Widget
{
public:
Widget() {cout << "created Base Widget\n";}
Widget(const Widget& original) noexcept {
cout << "copied Base Widget\n";
}
virtual ~Widget(){} // need virtual destructor with class hierarchy
virtual Widget* clone() const { // makes deep copies of pointers
if constexpr(noexcept(Widget(*this))) {
try {
cout << "cloned Widget\n";
return new Widget(*this);
}
catch(exception& e) {
throw runtime_error("error occurred while cloning Widget");
}
} else
throw logic_error("Widget: Faulty constructor");
}
};
class Button: public Widget{
public:
Button(): Widget() { cout << "created Button\n"; }
Button(const Button& original) noexcept: Widget(original){
cout << "copied Button\n";
}
virtual Button* clone() const {
if constexpr(noexcept(Button(*this))) {
try {
cout << "cloned Button\n";
return new Button(*this);
}
catch(exception& e) {
throw runtime_error("error occurred while cloning Button");
}
} else
throw logic_error("Button: Faulty constructor");
}
virtual ~Button(){}
};
class Label: public Widget {
public:
Label(): Widget() { cout << "created Label\n"; }
Label(const Label& original) noexcept: Widget(original){
cout << "copied Label\n";
}
virtual Label* clone() const {
if constexpr(noexcept(Label(*this))) {
try {
cout << "cloned Label\n";
return new Label(*this);
}
catch(exception& e) {
throw runtime_error("error occurred while cloning Label");
}
} else
throw logic_error("Label: Faulty constructor");
}
virtual ~Label(){}
};
class Plane { // destructor is needed so copy&move semantics are also needed
// (rule of 5)
vector<Widget*>vec;
public:
Plane(): vec(0) {}
Plane(const Plane& original) // performs deep copy
{
vec.resize(original.vec.size());
for (size_t i = 0; i != original.vec.size(); ++i)
vec[i] = original.vec[i]->clone();
}
Plane& operator=(const Plane& original)
{
if (this != &original) {
vec.resize(original.vec.size());
for (size_t i = 0; i != original.vec.size(); ++i)
vec[i] = original.vec[i]->clone();
}
return *this;
}
~Plane() {
for (auto w: vec) {
delete w;
cout << "deleted Widget\n";
}
}
// for completeness also add move semantics
Plane(Plane&& original) noexcept
{
vec = move(original.vec);
cout << "moved Plane\n";
}
Plane& operator=(Plane&& original) noexcept
{
if (this != &original)
vec.swap(original.vec);
return *this;
}
void Add (Widget* w) {
vec.push_back(w);
cout << "added Widget*\n";
}
};
int main () {
Plane p1;
p1.Add(new Button);
p1.Add(new Label);
Plane p2(p1);
return 0;
}
Results as expected: four Widget
s are delete
d (two in p1
and two in p2
)
created Base Widget
created Button
added Widget*
created Base Widget
created Label
added Widget*
cloned Button
copied Base Widget
copied Button
cloned Label
copied Base Widget
copied Label
deleted Widget
deleted Widget
deleted Widget
deleted Widget
Upvotes: 2