Wednesday 13 June 2018

c++ - Copy constructor destructor and assignment operator for class storing pointers to another class



I'm new here and this is my first question. I have a question about my homework assignment. I'm asked to design an abstract class "Base" which is inherited by the class "Sub" (in the assignment there are sub1, sub2 etc but I have tried to narrow it down as much as possible). Then, I should design a class "BasePtr" which stores a pointer to a "Base" object. Finally, baseptr:s are to be stored in a std::vector, and written to a file using ostream_iterator and copy. The file should then be read with a ifstream_iterator, and stored in a std::list.



I have solved the above problem, but I have some problems when implementing the destructor, copy constructor and assignment operator (since I am dynamically allocating memory in my BasePtr class I believe that those should be present).



This is the main program.



#include 

#include
#include
#include
#include "baseptr.h"

using namespace std;
int main()
{
vector basevec;
basevec.push_back( BasePtr(new Sub(1, 4)) );

basevec.push_back( BasePtr(new Sub(3, 5)) );

ofstream os("fil.dat");
ostream_iterator baseout(os,"\n");
copy( basevec.begin(), basevec.end(), baseout);
os.close();

ifstream is("fil.dat");
istream_iterator basein(is), endofbasein;
list baselist(basein, endofbasein );


for (list::iterator it = baselist.begin(); it != baselist.end(); it++)
cout << *it << endl;
}


The BasePtr class



#include 
#include

#include "base.h"

using namespace std;

class BasePtr {
public:
BasePtr() : basevar(0) {}
BasePtr(Base *bin) {basevar = bin->clone(); delete bin;}
const BasePtr & operator=( BasePtr & baseptr ); // assignment operator
BasePtr(const BasePtr &baseptr ); // copy constructor

~BasePtr(); // destructor
friend ostream& operator<<( ostream &os, const BasePtr &baseptr);
friend istream& operator>>( istream &is, BasePtr &baseptr);
private:
Base* basevar;
};

const BasePtr & BasePtr::operator=( BasePtr & baseptr ) {
if (this != &baseptr) {
delete basevar;

basevar = baseptr.basevar->clone();
}
return *this;
}

BasePtr::BasePtr( const BasePtr &baseptr ) {
if (baseptr.basevar != 0)
basevar = baseptr.basevar->clone();
}


BasePtr::~BasePtr() {
if ( basevar != 0 )
delete basevar;
basevar = 0;
}

ostream& operator<<( ostream &os, const BasePtr &baseptr) {
os << *baseptr.basevar;
return os;
}


istream& operator>>( istream &is, BasePtr &baseptr) {
string name;
if (!(is >> name))
return is;
Base *b = 0;
if ( name == "SUB" )
b = new Sub();
is >> *b;
baseptr.basevar = b->clone();

delete b;
return is;
}


and the Base and Sub classes



#include 
using namespace std;


class Base {
public:
virtual ~Base() {}
virtual Base* clone() const = 0;
friend ostream& operator<<( ostream &os, Base &b) {
b.print(os);
return os;}
friend istream& operator>>( istream &is, Base &b) {b.readStream(is); return is;}
protected:
Base(const double xin) : x(xin) {}

double x;
virtual ostream& print(ostream &os) const = 0;
virtual void readStream( istream &is ) = 0;

};


class Sub : public Base{
public:
Sub() : Base(0), size(0) {}

Sub(double xin, double si) : Base(xin), size(si) {}
~Sub() {};
Sub* clone() const {return new Sub(*this);}
private:
double size;
Sub(const Sub &p) : Base(p.x), size(p.size) {}
protected:
virtual ostream& print(ostream &os) const {os << "SUB " << x << " " << size << endl;
return os; }
virtual void readStream( istream &is ) {

is >> x;
is >> size;
}

};


If I comment out the destructor, copy constructor and assignment operator the program builds and runs, and outputs the desired result. However, valgrind finds loads of memory leaks (obviously). If I include these functions, the program ends with Segmentation fault: 11. I am using a mac with os x 10.8 and the clang compiler. What am I doing wrong?


Answer



The bug in your program is probably in the copy constructor:




BasePtr::BasePtr( const BasePtr &baseptr ) {
if (baseptr.basevar != 0)
basevar = baseptr.basevar->clone();
else {
basevar = 0; // <<<< missing
}
}



Without this change the following code will produce errors:



BasePtr a; // a.basevar = 0
BasePtr b = a; // now b.basevar is not initialized
// destruction of b will call delete on an uninitialized pointer

No comments:

Post a Comment

php - file_get_contents shows unexpected output while reading a file

I want to output an inline jpg image as a base64 encoded string, however when I do this : $contents = file_get_contents($filename); print &q...