OVH Cloud OVH Cloud

Problème avec un tableau d'objet

6 réponses
Avatar
smu
Bonjour,

Je débute en C++ et j'ai crée une classe incluant un compteur
d'instance. La classe que j'ai publiée ici ne contient que le minimum
pour se comporter correctement (voir ci-dessous).
Toutefois, j'ai un problème de syntaxe. Pour instancier un objet sur la
pile, il suffit de la déclarer :

simpleObject instance1("Single stack");

Pour instancier un objet sur le tas, il suffit de la déclarer :

simpleObject * const instance2 = new simpleObject("Single heap");

Mais si je veux instancier plusieurs objets de type simpleObject,
j'écris un truc du genre :

simpleObject * const instances = new simpleObject[4]("Multiple heap");

Mais là, j'ai une erreur à la compilation.

Doit-on créer un constructeur spécial pour les tableaux d'objet ?
Si oui, quelle est la syntaxe pour ce genre de constructeur ?

D'avance merci

smu

// testArrayNew.cpp

#include "simpleObject.h"
#include <iostream>

int main()
{
using namespace std;

simpleObject instance1("Single stack");
simpleObject * const instance2 = new simpleObject("Single heap");
// simpleObject * const instances = new simpleObject[4]("Multiple heap");

cout << "This program do nothing except instanciate 4 simpleObjects."
<< endl;

delete instance2;
// delete []instances;
cout << "The end" << endl;
return 0;
}

// simpleObject.h

#ifndef __SIMPLEOBJECT_HEADER__
#define __SIMPLEOBJECT_HEADER__

#include <string>

class simpleObject
{
static int counter;
int order;
std::string message;
public:
simpleObject(const std::string msg);
~simpleObject();
};

#endif // __SIMPLEOBJECT_HEADER__

// simpleObject.cpp

#include "simpleObject.h"
#include <iostream>
#include <string>

int simpleObject::counter = 0;

simpleObject::simpleObject(const std::string msg)
{
using namespace std;

message = msg;
cout << message << " ->" << endl;
if ((order = ++counter) == 1)
{
cout << "This is the first instantiation of simpleObject: " << endl <<
"\t";
}
cout << "Constructor: I'm the number " << order << " instance." << endl;
}

simpleObject::~simpleObject()
{
using namespace std;

cout << message << " ->" << endl;
if (--counter == 0)
{
cout << "This is the last instantiation of simpleObject: " << endl <<
"\t";
}
cout << "Destructor: I'm the number " << order << " instance." << endl;
}

6 réponses

Avatar
Fabien LE LEZ
On Mon, 15 Aug 2005 18:01:38 +0200, smu :

simpleObject * const instances = new simpleObject[4]("Multiple heap");

Mais là, j'ai une erreur à la compilation.


Effectivement, ce n'est pas possible.
Par contre, ceci fonctionne :

std::vector <simpleObject> table_instances
(4, simpleObject ("Multiple heap"));

Avatar
smu
On Mon, 15 Aug 2005 18:01:38 +0200, smu :


simpleObject * const instances = new simpleObject[4]("Multiple heap");

Mais là, j'ai une erreur à la compilation.



Effectivement, ce n'est pas possible.
Par contre, ceci fonctionne :

std::vector <simpleObject> table_instances
(4, simpleObject ("Multiple heap"));


Merci pour votre solution.


Mais avant d'attaquer les templates, est il possible de définir un
constructeur spécial tel qu'on le fait avec "operator new" et "operator
new[]" ?

smu


Avatar
Fabien LE LEZ
On Mon, 15 Aug 2005 18:39:26 +0200, smu :

Mais avant d'attaquer les templates


L'usage de std::vector<> fait partie des connaissances basiques -- à
étudier bien avant "new", car c'est à la fois beaucoup plus simple et
beaucoup plus utile.

Avatar
Matthieu Moy
Fabien LE LEZ writes:

On Mon, 15 Aug 2005 18:39:26 +0200, smu :

Mais avant d'attaquer les templates


L'usage de std::vector<> fait partie des connaissances basiques -- à
étudier bien avant "new", car c'est à la fois beaucoup plus simple et
beaucoup plus utile.


En fait, définir un template en C++ est sans doute à classer dans la
catégorie des choses compliquées pour un débutant, par contre, en
utiliser un, s'il est bien fait, est relativement simple.

--
Matthieu


Avatar
smu
On Mon, 15 Aug 2005 18:39:26 +0200, smu :


Mais avant d'attaquer les templates



L'usage de std::vector<> fait partie des connaissances basiques -- à
étudier bien avant "new", car c'est à la fois beaucoup plus simple et
beaucoup plus utile.



Effectivement, c'est très simple et fonctionne très bien avec gcc. Mais,
parce qu'il y a un "mais", le compilo de m...e que je suis obligé
d'utiliser ne comprends pas l'expression en question.
Donc je reviens à la charge pour une syntaxe qui me permettrais
d'instancier les quatre objets tout en les initialisant.

Le code ci-dessous permet d'utiliser le constructeur par défaut :

simpleObject * const instances1 = new simpleObject[4];

Mais il faudrait que je puisse initialiser chacun des instances :

simpleObject * const instances1[] = {new simpleObject("Multiple heap 1"),
new simpleObject("Multiple heap 2"),
new simpleObject("Multiple heap 3"),
new simpleObject("Multiple heap 4")};

Si vous avez une idée (voir une solution), je suis preneur.

D'avance merci

smu

P.S. J'ai, à nouveau, publié les sources puisque je l'ai modifié.

// testArrayNew.cpp

#include "simpleObject.h"
#include <iostream>

int main()
{
using namespace std;

simpleObject instance1("Single stack");
simpleObject * const instance2 = new simpleObject("Single heap");
simpleObject * const instances1 = new simpleObject[4];
/*
simpleObject * const instances1[] = {new simpleObject("Multiple heap"),
new simpleObject("Multiple
heap"),
new simpleObject("Multiple
heap"),
new simpleObject("Multiple
heap")};
*/
simpleObject instances2[4] = { simpleObject("Multiple stack"),
simpleObject("Multiple
stack"), simpleObject("Multiple
stack"),
simpleObject("Multiple stack")};

cout << endl << "This program do nothing except instanciate " <<
simpleObject::howManyObject() << " simpleObjects." << endl << endl;

delete instance2;
delete []instances1;
cout << "The end" << endl;
return 0;
}

// simpleObject.h

#ifndef __SIMPLEOBJECT_HEADER__
#define __SIMPLEOBJECT_HEADER__

#include <string>

class simpleObject
{
static int counter;
int order;
std::string message;
public:
simpleObject();
simpleObject(const std::string msg);
simpleObject(simpleObject& object);
~simpleObject();
static int howManyObject();
};

#endif // __SIMPLEOBJECT_HEADER__

// simpleObject.cpp

#include "simpleObject.h"
#include <iostream>
#include <string>

int simpleObject::counter = 0;

simpleObject::simpleObject()
{
using namespace std;

message = "Default constructor";
order = ++counter;
cout << "Constructor (" << message << "): I'm the instance number " <<
order << endl;
if (order == 1)
{
cout << "tThis is the first simpleObject instance." << endl;
}
}

simpleObject::simpleObject(const std::string msg)
{
using namespace std;

message = msg;
order = ++counter;
cout << "Constructor (" << message << "): I'm the instance number " <<
order << endl;
if (order == 1)
{
cout << "tThis is the first simpleObject instance." << endl;
}
}

simpleObject::simpleObject(simpleObject& object)
{
using namespace std;

order = object.order;
message = object.message;
counter++;
cout << "Copy-constructor on object " << order << endl;
}

simpleObject::~simpleObject()
{
using namespace std;

cout << "Destructor (" << message << "): I'm the instance number " <<
order << endl;
if (--counter == 0)
{
cout << "tThis is the last simpleObject instance." << endl;
}
}

int simpleObject::howManyObject()
{
return counter;
}


Avatar
Loïc Joly
L'usage de std::vector<> fait partie des connaissances basiques -- à
étudier bien avant "new", car c'est à la fois beaucoup plus simple et
beaucoup plus utile.



Effectivement, c'est très simple et fonctionne très bien avec gcc. Mais,
parce qu'il y a un "mais", le compilo de m...e que je suis obligé
d'utiliser ne comprends pas l'expression en question.


De quel compilo s'agit-il ? Histoire qu'on ait une idée des solutions
qui pourraient marcher...

Donc je reviens à la charge pour une syntaxe qui me permettrais
d'instancier les quatre objets tout en les initialisant.

Le code ci-dessous permet d'utiliser le constructeur par défaut :

simpleObject * const instances1 = new simpleObject[4];

Mais il faudrait que je puisse initialiser chacun des instances :

simpleObject * const instances1[] = {new simpleObject("Multiple heap 1"),
new simpleObject("Multiple heap 2"),
new simpleObject("Multiple heap 3"),
new simpleObject("Multiple heap 4")};


Ce n'est pas possible directement, à moins que simpleObject soit un POD.
Un tableau d'objets avec constructeur est toujours construit par le
constructeur par défaut.

Quelques pistes :

- Faire un tableau de pointeur, puis créer les objets par new
- Faire des tes objets des POD (en gros, des structs à la C, avec des
fonctions membre mais ni constructeur, ni destructeur, ni fonction
virtuelles...)
- Faire comme fait vector, à savoir allouer de la mémoire non
initialisée (avec un truc comme simpleObject *mem =
static_cast<simpleObject*> (new char [n*sizeof(simpleObject])), puis
utiliser un placement new pour construire l'objet dans la mémoire
allouée (new (mem+i) simpleObject("Multiple heap 1"))

--
Loïc