2009-05-11 13 views
2

J'essaie de créer un tableau d'objets de classe prenant un argument entier. Je ne vois pas ce qui ne va pas avec ce simple petit code. Quelqu'un pourrait-il aider?Besoin d'aide pour créer un tableau d'objets

#include <fstream> 
#include <iostream> 
using namespace std; 

typedef class Object 
{ 
int var; 
public: 
Object(const int& varin) : var(varin) {} 
} Object; 

int main (int argc, char * const argv[]) 
{ 
for(int i = 0; i < 10; i++) 
{ 
    Object o(i)[100]; 
} 

return 0; 
} 

Répondre

8

En C++ vous n'avez pas besoin typedef s pour class es et struct s. Alors:

class Object 
{ 
int var; 
public: 
Object(const int& varin) : var(varin) {} 
}; 

En outre, des noms descriptifs sont toujours preferrable, Object est beaucoup abusé.

int main (int argc, char * const argv[]) 
{ 
int var = 1; 

Object obj_array[10]; // would work if Object has a trivial ctor 

return 0; 
} 

Sinon, dans votre cas:

int main (int argc, char * const argv[]) 
{ 
int var = 1; 

Object init(var); 
Object obj_array[10] = { var, ..., var }; // initialize manually 

return 0; 
} 

Bien que, vraiment, vous devriez chercher vector

#include <vector> 
int main (int argc, char * const argv[]) 
{ 
int var = 1; 

vector<Object> obj_vector(10, var); // initialize 10 objects with var value 

return 0; 
} 
4

diminution des effectifs de dirkgently est une représentation assez précise des tableaux d'objets en C++, mais où il initialise tous les éléments du tableau avec la même valeur, il semble que vous essayez d'initialiser chacun avec une valeur distincte.

Pour répondre à votre question, créez un tableau d'objets qui prennent un paramètre de constructeur int. Vous ne pouvez pas, les objets sont créés lorsque le tableau est alloué et en l'absence d'un constructeur trivial votre compilateur va se plaindre. Vous pouvez toutefois initialiser un tableau de pointeurs sur votre objet, mais vous obtenez vraiment beaucoup plus de flexibilité avec un vecteur, donc mes exemples suivants utiliseront std :: vector.

Vous devrez initialiser chacun des objets séparément si vous voulez que chaque objet ait une valeur distincte, vous pouvez le faire de deux manières différentes; sur la pile, ou sur le tas. Regardons d'abord sur la pile.

Tout constructeur qui prend un argument unique et qui n'est pas marqué explicit peut être utilisé en tant que constructeur implicite. Cela signifie que n'importe quel endroit où un objet de ce type est attendu, vous pouvez utiliser une instance du type de paramètre unique. Dans cet exemple, nous créons un vecteur de votre classe Object et y ajoutons 100 objets (push_back ajoute des éléments à un vecteur), nous passons un entier dans push_back qui crée implicitement un objet passant dans l'entier.

#include <vector> 
int main() { 
    std::vector<Object> v; 

    for(int i = 0; i < 100; i++) { 
     v.push_back(i); 
    } 
} 

Ou, pour être explicite à ce sujet:

#include <vector> 
int main() { 
    std::vector<Object> v; 

    for(int i = 0; i < 100; i++) { 
     v.push_back(Object(i)); 
    } 
} 

Dans ces exemples, tous les objets d'objets sont attribués sur la pile dans le cadre de la boucle, donc une copie se produit lorsque l'objet est poussé dans le vecteur. La copie d'un grand nombre d'objets peut entraîner des problèmes de performances, en particulier si votre objet est coûteux à copier.

Une façon de contourner ce problème de performance est d'allouer les objets sur les pointeurs de tas et de stocker les objets dans votre vecteur:

#include <vector> 
int main() { 
    std::vector<Object*> v; 

    for(int i = 0; i < 100; i++) { 
     v.push_back(new Object(i)); 
    } 

    for(int i = 0; i < 100; i++) { 
     delete v[i]; 
    } 
} 

Depuis nos objets ont été créés sur le tas, nous devons nous assurer que nous les supprimions pour appeler leur déconstructeur et, libérer leur mémoire, ce code le fait dans la deuxième boucle.

Appeler manuellement delete a ses propres limites, si vous passez ces pointeurs vers un autre code, vous pouvez rapidement perdre la trace de qui possède les pointeurs et qui doit les supprimer. Un moyen plus facile de résoudre ce problème est d'utiliser un pointeur intelligent pour suivre la durée de vie du pointeur, voir soit boost::shared_ptr ou tr1::shared_ptr qui sont des pointeurs comptage de références:

#include <vector> 
int main() { 
    std::vector<shared_ptr<Object> > v; 

    for(int i = 0; i < 100; i++) { 
     Object* o = new Object(i); 
     v.push_back(shared_ptr<Object>(o)); 
    } 
} 

Vous remarquerez que le constructeur shared_ptr est explicite , ceci est fait intentionnellement pour s'assurer que le développeur bourre intentionnellement son pointeur dans le pointeur partagé. Lorsque toutes les références à un objet sont libérées, l'objet sera automatiquement supprimé par shared_ptr, nous libérant du besoin de s'inquiéter de sa durée de vie.

+0

Merci pour le suivi. C'était aussi une aide précieuse! – banDedo

0

Si vous voulez vous en tenir à des tableaux, vous devez soit initialiser manuellement soit utiliser le constructeur par défaut. Cependant, vous pouvez obtenir un certain contrôle en créant un constructeur avec un argument par défaut. Cela sera traité comme un constructeur par défaut par le compilateur. Par exemple, le code suivant imprime les numéros 0, ..., 9 dans l'ordre. (Cependant, je ne suis pas sûr que la norme exige que les objets du tableau doivent être construits dans l'ordre. Il pourrait être mise en œuvre dépend, dans ce cas, les chiffres peuvent apparaître dans un ordre arbitraire.)

#include <iostream> 

using namespace std; 

struct A { 
    int _val; 

    A(int val = initializer()) : _val(val) {} 

    static int initializer() { static int v = 0; return v++; } 
}; 

int main() 
{ 
    A a[10]; 
    for(int i = 0; i < 10; i++) 
     cout << a[i]._val << endl; 
} 
Questions connexes