Using destructor in class - c++

I've got a project in C++ that uses classes(quite basic elements).
My class looks like this:
class vehicule: public frane,public motor,public directie,public noxe,public caroserie
{
char tip[40];
int placfatacant,placfatatot;
static const int placfatapret=18;
int placspatecant,placspatetot;
static const int placspatepret=15;
public:
vehicule()
void settip(char)
void verifauto()
;};
I've been told I have to use copy constructor and destructor. I have some examples,but both use dynamic allocation. Now my question is:what should my copy constructor/destructor do as I don't have dynamic allocated memory to copy/delete? Or should I declare the data as
int *placfatacant
and then use
delete placfatacant
?
Thanks in advance!

You only need to declare a constructor if you need to handle the deletion of dynamically allocated variables, as you said. In general, for every new, there must be a delete.
I don't see any new'd objects in your class, so I would just let the compiler-generated destructor/copy constructor do its thing. Your class is entirely statically allocated and will be deleted when it falls out of scope of the context in which it is used.

If it is for school purpose you can change :
// From:
char tip[40];
// To:
char * tip;`
And then in your constructor you will make:
tip = new char[40]();
Now you have to create a copy constructor like this one:
vehicule(const vehicule & toCopy)
{
tip = new char[40]();
strcpy(tip, toCopy.tip);
}
Your destructor just need to deallocate tip:
~vehicule()
{
delete tip;
}

Related

Deleting an Object in c++ implies deletion of its members?

I am quite new to c++ and I have a question.
If I have a class containing a (pointer to a) vector:
class myClass {
public:
int* direction;
myClass(int d){direction=new int[d];}
}
When I create an object and delete it in the main:
int main(){
int d;
myClass* myvec;
myvec = new myClass(d);
delete myvec;
}
Also the destructor for myvec->direction has been coherently called and the memory freed? Or do I have to write an apposite method for that?
I hope the question is clear...
If you've allocated memory with new you need to delete it too, like this:
class myClass {
int* direction;
public:
myClass(int d) : direction(new int[d]) {}
~myClass() {
delete[] direction;
}
}
But you'd also need to write a copy constructor and copy assignment operator, and in C++11 and later also a move constructor and move assignment operator, for this to be working good. Otherwise, you'd risk the default versions of those copying the raw pointer when you use instances of this class.
Take a look at the rule of three/five/zero.
You'd be much better off using a std::vector<int> instead of a raw pointer.

C++11 class attribute as another object?

I'm working on some C++11 examples, but i'm a little rusty. I'm trying to add an object instance to a class attribute. I have something like this:
Entity.h
class Entity {
private:
MyClass object;
public:
Entity();
void doTest();
};
Entity.cpp
#include "Entity.h"
Entity::Entity() {
}
void Entity::doTest(stuff) {
object = new MyClass(stuff);
}
Is this correct? How can i do this in C++?
It's all correct apart from the new. Only use that when you need dynamic allocation; in this case, you just want to create an object:
object = MyClass(stuff);
Or perhaps you want to initialise it in the constructor instead:
Entity(stuff) : object(stuff) {}
It is wrong. object is an object not a pointer. but your code
object = new MyClass(stuff);
treat object as a pointer.
You can either declare object as a pointer in the class Entity or change your function doTest;
If you want a pointer it is better to use smart pointers in C++, such as unique_ptr.
In C++ your object field is really an object. That means that there is an allocated memory inside every Entity object you may create. The problem is how you can initialize that object field ?
if MyClass has no ctor or a ctor callable with no parameter, everything is ok.
if not, you should define the initialization of the field at the same time you define the ctor of Entitythis way
Entity::Entity() : object(parameters) {
code for Entities initialization
}
this is a way to ensure the correctness of your initialization so that object is initialized before you have control on the initialization of the Entity.
Your object is statically initialized inside each Entity, this is a good way, in C++, to code what is called a composition in object oriented programming.
You want to use in the decleration:
MyClass* object
Also, if you are going to use new MyClass make sure you use delete object to avoid leaks.
i.e.
Entity::Entity() { object = NULL; } //constructor
Entity::doTest(stuff) {
delete object;
object = new MyClass(stuff);
}
//Following rule of three, since we need to manage the resources properly
//you should define Copy Constructor, Copy Assignment Operator, and destructor.
Entity::Entity(const Entity& that) { //copy constructor
object = that.object;
//assumes you've correctly implemented an assignment operator overload for MyClass
}
//invoke copy and swap idiom* if you wish, I'm too lazy
Entity& Entity::operator=(const Entity& source) {
MyClass* temp = new MyClass(source.object)
//assumes you've correctly implemented an copy constructor (or default one works) for MyClass.
delete object;
object = temp;
return *this;
}
Entity::~Entity() { //destuctor
delete object;
}
You should avoid dynamic allocation if it is at all possible. You should also use smart pointers (like std::shared_ptr) but if you do wish to use raw pointers, then abide by the rule of three.
*copy and swap idiom

Creating copy constructor for class with a pointer member on the heap

Short version: Can I safely create a copy constructor for a class that has member pointer variables, one of which is on the heap, that are of type xercesc::XercesDOMParser* and xercesc::DOMDocument*? If so, how?
Long version:
I wrote a class to wrap a Xercesc document object. It has two member variables that are pointers to a XercesDOMParser and a DOMDocument. Here is the part of the class declaration that shows those two members:
class XMLigator {
private:
xercesc::XercesDOMParser* _pParser;
xercesc::DOMDocument* _pDocument;
etc...
The pointers _pParser and _pDocument are initialized in the constructor. Here is an abbreviated version of the constructor with the relevant code. Notice that _pParser is created with the new operator and is on the heap:
XMLigator::XMLigator(string strFile) : _strFile(strFile), _pDocument(NULL) {
xercesc::XMLPlatformUtils::Initialize();
_pParser = new xercesc::XercesDOMParser();
_pParser->parse(_strFile.c_str());
_pDocument = _pParser->getDocument();
}
The destructor deletes the member variable _pParser:
XMLigator::~XMLigator(void) {
if (m_pParser) {
delete _pParser;
}
}
Until now I have prohibited the copy constructor and assignment operator by marking them private and not defining them.
Now I would like to, if possible, create a copy constructor for this class so I can make it a return type for a function, in this fashion:
XMLigator getOne() {
XMLigator xml("/some/file.xml");
return xml;
}
The first problem I see is my the destructor does a delete _pParser;. So I think that's a problem. I am pretty sure I have to remove the delete from the destructor. But then I have a memory leak.
I really have no idea how to approach this. Maybe it's not possible. Does anyone have an approach that I can use for this?

About destructors in c++

The question is how to correctly delete name in A destructor?
class A{
private:
char *name;
public:
A(char *n) : name(n) {}
~A(){
//???
}
}
int main(){
A *a = new A("name");
delete a;
return 0;
}
Given that you do not change the constructor, then the correct way is to not delete anything. Ownership of the string belongs to the client, since you are not creating a copy.
However, the right way of rewriting this is to let the constructor allocate a copy of the string with new[] and let the destructor deallocate it with delete[].
And the really right way is to let std::string do the whole thing for you, and not write an explicit destructor at all:
#include <string>
class A{
private:
std::string name;
public:
A(std::string n) : name(std::move(n)) {}
};
This, by the way, allows you not to worry about the Rule of Three, which means you won't have to bother writing a copy constructor, a move constructor, a copy assignment operator, a move assignment operator, a destructor and whatnot.
You are not allowed to delete a pointer to string constant "name".
As your class does not own any objects or memory blocks, it should not delete anything.
In this example you don't need to delete name. "name" is just a pointer to some some place in executable image, not memory allocated with new/malloc/something_else.
"name" occupies static memory that the compiler automatically sets aside. If you delete that memory, the behavior is undefined (i.e. crash). You only 'delete' memory that you 'new' in the first place.
The simplest thing is to use proper C++ (std::string) and avoid naked pointers, as that simplifies management of resources.
The problem with your interface is that the type A claims ownership of the argument, but you cannot claim ownership of a string literal, as those are managed by the implementation. You could go on trying to decide whether the caller should create deep copy and pass it to a A or if A design should be changed not to attempt to claim ownership and make a copy out of that. But the fact is that things are much simpler if you just use higher level constructs:
class A {
std::string name;
public:
A(const std::string& name) : name(name) {}
};
No need to manually copy data around, no need for a destructor or a copy constructor... all works out of the box.

Copy constructor c++ weird behavoir?

Hi I have a class which includes an array, I'm not passing this through my class constuctor (could be going wrong here?) The array is just defined in the class then initialized in a read method.
But in the main I make an instance of the class like:
myClass myClass1;
Then do:
myClass1 = myClass2;
Now I use a bubble sort method on the first class instance like:
MyClass1.sort();
Now when I write both of these instances out to text after the sort they are both sorted?
I have had a read into shallow and deep copys, but I can't understand why a method called after the shallow copy, would result in both of them being sorted? Is this expected behavoir?
a little more information:
In my class I just define the array as:
static string myArray[5];
then in a write method I write the 5 elements to it, is there a better way of doing this, I have to use a method to intialize it though.
How is your array defined/created? If you create it with new and reference it with a pointer, you'll need a custom copy constructor creating a deep copy (i.e. creating a new instance of the array and copying its contents). The default copy constructor will only do a shallow copy, so both instances would use the same memory (i.e. both pointers' point to the same array on the heap).
This will work with the default copy constructor:
class myclass {
char text[256];
}
This won't work with the default copy constructor (at least not as expected):
class myclass {
char *text;
myclass() : text(new char[256]) {}
~myclass() { delete [] text; }
}
A member defined as static will never be copied. All instances share it without further code required:
class myclass {
static char text[256];
}
A copy constructor for the second case could look like this (note this is simplified and not checking for valid values and such):
myclass(const myclass &base) : text(new char[256]) { strcpy(text, base.text); }
General rule of thumb:
Do I use any pointer member that is assigned the return value of some new? If so, write a copy constructor. If not, hen use he default one (unless you've got other reasons).
In my class I just define the array as:
static string myArray[5];
Should I declare it in the header, as its only declared in the cpp file? As its still copying both.
If you declare that outside of a class definition it will be a global variable. There will only be one instance of it. You need to declare it inside the class, and not static:
class MyClass1 {
// other things...
string myArray[5];
};
In any case, this kind of basic question is better answered by consulting a good C++ introductory book.