2009-08-29 9 views
4

Je suis assez nouveau pour C++, surtout dans ses techniques. Ma question est, comment puis-je créer un membre d'objet statique d'une classe elle-même. Ce que je veux dire, c'est que j'ai déclaré un objet membre statique dans une classe. Exemple:Comment créer un membre d'objet statique de classe?

CFoo:CFoo *pFoo[2] = {0}; 

class CFoo 
{ 
    public: static CFoo *pFoo[2]; 
    public: CFoo(int a); 
    public: CFoo *getFoo(); 
}; 

Maintenant, le problème est, comment puis-je créer le pFoo, comme je veux créer deux objets statiques pFoo,

pFoo[0] = new CFoo(0); 
pFoo[1] = new CFoo(1); 

pour que je puisse utiliser la méthode getFoo pour retourner l'un des le pFoo, comme,

CFoo *getFoo() 
{ 
    return pFoo[0]; //or pFoo(1); 
} 

Merci beaucoup les gars. J'espère que mes questions sont claires.

Merci encore à l'avance. -sasayins

Répondre

19

Améliorons votre code une étape à la fois. Je vais expliquer ce que je fais à chaque étape.

Étape 1, ce n'est pas Java. Vous n'avez pas besoin de spécifier public pour chaque membre. Tout après public: est public jusqu'à ce que vous spécifiez autre chose (protected ou private). J'ai également déplacé la définition de pFoo après la classe.Vous ne pouvez pas définir une variable avant qu'elle ne soit déclarée.

class CFoo 
{ 
    public: 
     static CFoo *pFoo[2]; 
     CFoo(int a); 
     CFoo *getFoo(); 
}; 

CFoo* CFoo::pFoo[2] = {0}; 

Étape 2, pFoo probablement ne devrait pas être publique si vous allez avoir une fonction membre getFoo. Appliquons l'interface à la classe au lieu d'exposer les données internes.

class CFoo 
{ 
    public: 
     CFoo(int a); 
     CFoo *getFoo(); 

    private: 
     static CFoo *pFoo[2]; 
}; 

CFoo* CFoo::pFoo[2] = {0}; 

étape 3, vous pouvez retourner par pointeur sans prendre la peine d'utiliser new. J'ai écrit du code C++ pendant de nombreuses années, et je devrais rechercher comment vous delete la mémoire qui a été créée pour une variable membre statique. Cela ne vaut pas la peine de le comprendre, alors allouons-les simplement sur la pile. En outre, retournons-les par le pointeur const pour empêcher les utilisateurs de modifier accidentellement les deux objets 0ooCFoo.

class CFoo 
{ 
    public: 
     CFoo(int a); 
     const CFoo *getFoo(); 

    private: 
     static CFoo foos[2]; 
}; 

CFoo CFoo::foos[2] = {CFoo(0), CFoo(1)}; 

La mise en œuvre de getFoo devient alors:

const CFoo * CFoo::getFoo() 
{ 
    return &foos[0]; // or &foos[1] 
} 

IIRC, l'organe statique foos sera alloué la première fois que vous créez un objet CFoo. Donc, ce code ...

CFoo bar; 
const CFoo *baz = bar.getFoo(); 

... est sûr. Le pointeur nommé baz pointe vers le membre statique foos[0].

+1

Vous soulevez autant de bons points, je voudrais vous donner trois votes. – sbi

+0

+1 très bon conseil. En outre, il n'y a vraiment aucun moyen fiable de libérer la mémoire donnée aux membres statiques à moins que vous ne le fassiez explicitement. Il restera alloué jusqu'à la fin du programme. –

+0

merci beaucoup beaucoup. mais que faire si je veux créer un objet en utilisant CFoo, comme par exemple, CFoo * pFoos [2]; pFoos [0] = nouveau CFoo; pFoos [1] = nouveau CFoo; Puis, ma question est la suivante: les foos [0] et les foos [1] ont-ils été alloués? – domlao

6

Vous n'avez pas besoin des pointeurs ici. En fait, ils ne sont probablement pas une bonne idée.

Le code suivant fonctionne pour moi:

#include <iostream> 

struct Foo { 
    static Foo const foos[]; 

    Foo(int i) : i(i) { } 

    int i; 
}; 

Foo const Foo::foos[2] = { Foo(1), Foo(2) }; 

using namespace std; 

int main() { 
    cout << Foo::foos[0].i << endl; 
} 

(Notez que (pour garder la simple démo) Je l'ai fait tous les membres public, ce qui est probablement pas ce que vous voulez fonctionne aussi. . bien avec les membres privés)

3

Pour initialiser votre tableau, vous devez écrire ceci:

CFoo* CFoo::pFoo [2] = { new CFoo(0), new CFoo(1) }; 

ne pas libérer le m Emory alloué de cette façon.

+0

+1 pour "Ne pas libérer la mémoire allouée de cette manière." –

+0

@Pavel: Attention: Vos objets CFoo ne seront pas automatiquement détruits à l'arrêt de l'application (initialisation et destruction statiques). – moala

+0

Ils ne seront pas libérés automatiquement, bien sûr. Mais vous ne devriez pas les libérer manuellement non plus. –

2

Il y a plusieurs façons de procéder. L'un est juste pour continuer à faire comme vous faites et initialiser le tableau pFoo comme celui-ci

// In source file (not header) 
CFoo* CFoo::pFoo[2] = {new CFoo(1), new CFoo(2)}; 

Mais je suggère de les envelopper dans un accesseur comme ceci:

// In header 
class CFoo 
{ 
public: 
    CFoo(int a); 
    CFoo* getFoo1() const; 
    CFoo* getFoo2() const; 

private: 
    static CFoo* getFoo(int n); 
}; 

// In source file 

CFoo::CFoo(int a) 
{ 
// Constructor implementation 
} 

CFoo* CFoo::getFoo1() const 
{ 
    return getFoo(1); 
} 

CFoo* CFoo::getFoo2() const 
{ 
    return getFoo(2); 
} 

CFoo* CFoo::getFoo(int n) 
{ 
    static CFoo* pFoo[2] = {new Foo(1), new Foo(2)}; 
    return pFoo[n]; 
} 

La raison principale est que cette contourne le fiasco de l'ordre d'initialisation statique. Lorsque vous avez une variable statique dans une classe, elle est quelque peu non déterministe lorsqu'elle est initialisée, ce qui est dangereux surtout quand la variable est publique. Envelopper dans un accesseur signifie que la variable sera initialisée lorsque l'accesseur est appelé pour la première fois, et ainsi vous saurez qu'il est initialisé avant d'essayer de l'utiliser. De plus, vous bénéficiez d'une initialisation paresseuse si elle n'est pas utilisée pendant un certain temps ou pas du tout.

Le code ci-dessus n'est pas adapté aux threads, mais je doute que vous utilisiez des threads ici.

De même, vous devriez probablement revoir votre style de codage. Préfixer des classes avec C est une pratique quelque peu archaïque, et mettre "public:" avant que chaque fonction publique soit bizarre, il suffit de l'écrire une seule fois.

Questions connexes