urobins
asked on
Destructor, do I need one? C++
I am working on my assignment for a class, everything works, but when reading about copy constructors they often mention needing a destructor. I wasn't sure if I needed one. It seems that most examples are using arrays or dynamic content, which I don't use. Can you look at my code and say if I need one? Thanks!
// Fig. 8.16: complex1.cpp
// Complex class member function definitions.
//Used the multiplication algorhythm posted in week 11 conference.
//Had some help from various sources tweaking my overloading.
#include <iostream>
using std::cout;
#include"complex1.h"// Complex class definition
// constructor
Complex::Complex( double realPart, double imaginaryPart )
: real( realPart ),
imaginary( imaginaryPart )
{
// empty body
} // end Complex constructor
//Copy Constructor
Complex::Complex(const Complex& operand2)
{
real = operand2.real;
imaginary = operand2.imaginary;
}
// addition operator
Complex Complex::operator+( const Complex &operand2 ) const
{
return Complex( real + operand2.real,
imaginary + operand2.imaginary );
} // end function operator+
// subtraction operator
Complex Complex::operator-( const Complex &operand2 ) const
{
return Complex( real - operand2.real,
imaginary - operand2.imaginary );
} // end function operator-
// I used the algorhthym posted in our conference. I had something similar but my parens were off I think :)
Complex Complex::operator*( const Complex &operand2 ) const
{
return Complex( ((real * operand2.real)-(imaginary * operand2.imaginary)), ((real * operand2.imaginary)+(opera nd2.real * imaginary)) );
} // end function operator*
Complex Complex::operator=(const Complex& operand2 )
{
if (this != &operand2)
{
real = operand2.real;
imaginary = operand2.imaginary;
}
return *this;
}
std::ostream& operator<<(std::ostream& stream,const Complex& complexNumber)
{
stream << "(" << complexNumber.getReal() << " , " << complexNumber.getImaginary ()<<")" ;
return stream;
}
std::istream& operator>>(std::istream& stream,Complex& value)
{
double realPart, imaginaryPart;
stream >> realPart >> imaginaryPart;
value.getReal(realPart);
value.getImaginary(imagina ryPart);
return stream;
}
bool Complex::operator==( const Complex &operand2 ) const
{
if (real == operand2.real && imaginary == operand2.imaginary)
return true;
else
return false;
}
bool Complex::operator!=( const Complex &operand2 ) const
{
if (real != operand2.real || imaginary != operand2.imaginary)
return true;
else
return false;
}
---------------
#ifndef COMPLEX1_H
#define COMPLEX1_H
class Complex {
public:
Complex( double = 0.0, double = 0.0 ); // constructor
Complex(const Complex& operand2); //Copy Constructor
Complex operator+( const Complex & ) const; // addition
Complex operator-( const Complex & ) const; // subtraction
Complex operator*( const Complex &operand2 ) const; // Multiplication
Complex operator=( const Complex& operand2 ); //overloaded assignment operator
bool operator==( const Complex &operand2 ) const;
bool operator!=( const Complex &operand2 ) const;
//Friend overloaded Stream operators
friend std::ostream &operator<<(std::ostream &stream, const Complex &value);
friend std::istream &operator>>(std::istream &stream, Complex &value);
//accessor functions
double getReal() const { return real; }
double getImaginary() const { return imaginary; }
void getReal(double r) { real = r; }
void getImaginary(double i) { imaginary = i; }
private:
double real; // real part
double imaginary; // imaginary part
}; // end class Complex
#endif
// Fig. 8.16: complex1.cpp
// Complex class member function definitions.
//Used the multiplication algorhythm posted in week 11 conference.
//Had some help from various sources tweaking my overloading.
#include <iostream>
using std::cout;
#include"complex1.h"// Complex class definition
// constructor
Complex::Complex( double realPart, double imaginaryPart )
: real( realPart ),
imaginary( imaginaryPart )
{
// empty body
} // end Complex constructor
//Copy Constructor
Complex::Complex(const Complex& operand2)
{
real = operand2.real;
imaginary = operand2.imaginary;
}
// addition operator
Complex Complex::operator+( const Complex &operand2 ) const
{
return Complex( real + operand2.real,
imaginary + operand2.imaginary );
} // end function operator+
// subtraction operator
Complex Complex::operator-( const Complex &operand2 ) const
{
return Complex( real - operand2.real,
imaginary - operand2.imaginary );
} // end function operator-
// I used the algorhthym posted in our conference. I had something similar but my parens were off I think :)
Complex Complex::operator*( const Complex &operand2 ) const
{
return Complex( ((real * operand2.real)-(imaginary * operand2.imaginary)), ((real * operand2.imaginary)+(opera
} // end function operator*
Complex Complex::operator=(const Complex& operand2 )
{
if (this != &operand2)
{
real = operand2.real;
imaginary = operand2.imaginary;
}
return *this;
}
std::ostream& operator<<(std::ostream& stream,const Complex& complexNumber)
{
stream << "(" << complexNumber.getReal() << " , " << complexNumber.getImaginary
return stream;
}
std::istream& operator>>(std::istream& stream,Complex& value)
{
double realPart, imaginaryPart;
stream >> realPart >> imaginaryPart;
value.getReal(realPart);
value.getImaginary(imagina
return stream;
}
bool Complex::operator==( const Complex &operand2 ) const
{
if (real == operand2.real && imaginary == operand2.imaginary)
return true;
else
return false;
}
bool Complex::operator!=( const Complex &operand2 ) const
{
if (real != operand2.real || imaginary != operand2.imaginary)
return true;
else
return false;
}
---------------
#ifndef COMPLEX1_H
#define COMPLEX1_H
class Complex {
public:
Complex( double = 0.0, double = 0.0 ); // constructor
Complex(const Complex& operand2); //Copy Constructor
Complex operator+( const Complex & ) const; // addition
Complex operator-( const Complex & ) const; // subtraction
Complex operator*( const Complex &operand2 ) const; // Multiplication
Complex operator=( const Complex& operand2 ); //overloaded assignment operator
bool operator==( const Complex &operand2 ) const;
bool operator!=( const Complex &operand2 ) const;
//Friend overloaded Stream operators
friend std::ostream &operator<<(std::ostream &stream, const Complex &value);
friend std::istream &operator>>(std::istream &stream, Complex &value);
//accessor functions
double getReal() const { return real; }
double getImaginary() const { return imaginary; }
void getReal(double r) { real = r; }
void getImaginary(double i) { imaginary = i; }
private:
double real; // real part
double imaginary; // imaginary part
}; // end class Complex
#endif
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
You guys are quick by the way :)
Almost :
Complex::~Complex()
{
}
Complex::~Complex()
{
}
ASKER
oh doh! Thanks guys. I'm gonna split the points between you guys since I saw both answers at the same time, as always you guys are great!
ASKER
As always Ininity08 and AndyAinscow were quick and provided the correct answer. Stellar support and friendly too.
Previous experts have clearly stated that constructor is unnecessay but desirable.
Still there is a use for your destructor (and your constructor too). You can use it to detect memory leaks, when you forget to free dynamically allocated objects:
public class Complex
{
public:
static int objectCount = 0;
Complex( double = 0.0, double = 0.0 ); // constructor
Complex(const Complex& operand2); //Copy Constructor
~Complex(); // destructor
}
Complex::Complex( double realPart, double imaginaryPart ) : real( realPart ), imaginary( imaginaryPart )
{
objectCount++;
}
Complex::Complex(const Complex& operand2)
{
real = operand2.real;
imaginary = operand2.imaginary;
objectCount++;
}
Complex::~Complex()
{
objectCount--;
}
So, before ending your application, objectCount should be 0, if not, there is a memory leak.
Also you can put messages in both contructors and destructor, for testing purposes.
Still there is a use for your destructor (and your constructor too). You can use it to detect memory leaks, when you forget to free dynamically allocated objects:
public class Complex
{
public:
static int objectCount = 0;
Complex( double = 0.0, double = 0.0 ); // constructor
Complex(const Complex& operand2); //Copy Constructor
~Complex(); // destructor
}
Complex::Complex( double realPart, double imaginaryPart ) : real( realPart ), imaginary( imaginaryPart )
{
objectCount++;
}
Complex::Complex(const Complex& operand2)
{
real = operand2.real;
imaginary = operand2.imaginary;
objectCount++;
}
Complex::~Complex()
{
objectCount--;
}
So, before ending your application, objectCount should be 0, if not, there is a memory leak.
Also you can put messages in both contructors and destructor, for testing purposes.
ASKER
Thanks jaime_olivares, I appreciate the addition! I looked at the link you provided about overloading my assignment operator and that is where I saw the destructor referenced. I proceeded to look into that and it always showed deleteing or setting some value to 0 but it didn't appear I really had anything like that, so I was a bit confused. I have everything working now, so thanks again to everyone who helped getting me going the right direction!
sorry!!! big typo!!! Instead of:
>>Previous experts have clearly stated that constructor is unnecessay but desirable.
should be:
Previous experts have clearly stated that DESTRUCTOR is unnecessay but desirable.
>>Previous experts have clearly stated that constructor is unnecessay but desirable.
should be:
Previous experts have clearly stated that DESTRUCTOR is unnecessay but desirable.
ASKER
HAHA I didn't even notice it said Destructor over constructor :) I read what I wanted to see I guess :)
ASKER
Complex::~Complex
{
}
Is that correct?