2010-01-03 7 views
3

Existe-t-il un meilleur moyen d'initialiser les structures C dans le code C++?Initialisation des structures C dans le code C++

Je peux utiliser des listes d'initialisation au point de déclaration de variable; cependant, ceci n'est pas utile si tous les arguments ne sont pas connus au moment de la compilation, ou si je ne déclare pas une instance locale/globale, par exemple:

Code C hérité qui déclare la structure, et possède également des API utilisant il

typedef struct 
{ 
    int x, y, z; 
} MyStruct; 

C++ code en utilisant la bibliothèque C

void doSomething(std::vector<MyStruct> &items) 
{ 
    items.push_back(MyStruct(5,rand()%100,items.size()));//doesn't work because there is no such constructor 
    items.push_back({5,rand()%100,items.size()});//not allowed either 

    //works, but much more to write... 
    MyStruct v; 
    v.x = 5; 
    v.y = rand()%100; 
    v.z = items.size(); 
    items.push_back(v); 
} 

Création d'instances locales et la mise en chaque membre un à la fois (myStruct.x = 5; etc) est une vraie douleur, et un peu difficile à lire en essayant de ajouter dire 20 différents articles au conteneur ...

+3

êtes-vous à la recherche d'une solution en C ou C++? – Christoph

Répondre

7

Si vous ne pouvez pas ajouter un constructeur (ce qui est la meilleure solution en C++ 03 mais vous avez probablement contrainte de compatibilité avec C), vous pouvez écrire une fonction avec le même effet:

MyStruct makeAMyStruct(int x, int y, int z) 
{ 
    MyStruct result = { x, y, z }; 
    return result; 
} 

items.push_back(makeAMyStruct(5,rand()%100,items.size())); 

Edit: J'ai vérifié maintenant que C++ 0X offre quelque chose pour ce problème précis:

items.push_back(MyStruct{5,rand()%100,items.size()}); 

qui est disponible en g ++ 4.4 .

+0

+1: Je pense que c'est la réponse qu'il recherche – Christoph

+0

btw: pourquoi ne pas utiliser une liste d'initialisation? – Christoph

+0

Aucune bonne raison, je vais changer ma fonction. – AProgrammer

7

Vous recherchez des littéraux composés C99. Exemple de code:

struct foo *foo = malloc(sizeof *foo); 
*foo = (struct foo){ bar, baz }; 
+0

Cela ressemble à une excellente solution, si elle était supportée par le compilateur (VC++ 9) :( –

+2

cette fois, ce n'est pas la faute du compilateur car les littéraux composés sont une fonctionnalité C99 non supportée par C++, j'ai mal interprété votre question cherchaient une solution en C ... – Christoph

+0

voir http://stackoverflow.com/questions/1705147/struct-initialization-of-the-cc-programming-language/1705166#1705166 pour quelques explications et le C++ 0x syntaxe – Christoph

3

Que diriez-vous:

MyStruct v = {5, rand()%100, items.size()}; 
items.push_back(v); 
+0

Donc, pour faire plusieurs choses mal à faire v1, v2, v3, v4 etc, pas moyen de réutiliser le local? –

+0

Si vous avez v1, v2, v3 et v4, vous êtes obligé d'écrire quelque chose 4 fois - à moins que vous vouliez qu'ils aient la même valeur, auquel cas vous pouvez faire des affectations simples, bien sûr. Si vous aviez v [0], v [1], v [2], v [3] et v [4], vous pourriez utiliser une boucle à la place. –

+0

Je ne suis pas sûr à 100% à ce sujet, mais je pense: MyStruct vs [2] = {{1, 2, 3}, {2, 3, 4}}; va travailler – James

2

ne sait pas ce que vous demandez. En C++, la solution évidente est de donner au struct un constructeur:

struct MyStruct { 
    int x, y, z; 
    MyStruct(int ax, int ay, int az) : x(ax), y(ay), z(az) {} 
}; 
+0

il cherche une solution en C – Christoph

+0

Il est marqué C++ si – James

+0

Alors pourquoi est-il étiqueté C++? C'est pourquoi j'ai dit que je n'étais pas clair. –

2

Créez une fonction pour l'initialiser, similaire à celle d'un constructeur C++.

+0

(+1) KISS répond de toutes les perspectives. –

1

Une autre option consiste à dériver de la structure et à y ajouter un constructeur. Ensuite, vous pouvez utiliser ce type dérivé dans votre propre code et le transmettre à la bibliothèque C lorsque cela est nécessaire. La langue devrait prendre soin de convertir implicitement à MyStruct le cas échéant. En prime, vous pouvez également ajouter d'autres fonctions membres utiles, peut-être même envelopper de nombreuses fonctions C héritées qui utilisent ce type.