2009-06-06 7 views
2

Je ne suis pas un expert en C++ et je n'ai toujours pas une bonne compréhension intuitive de la façon dont les choses fonctionnent. Je pense que c'est une question simple. J'ai du mal à passer des objets avec l'état à d'autres objets. Je préférerais éviter de passer des pointeurs ou des références, car une fois que les objets initialisés sont configurés, je les appelle des millions de fois dans une boucle serrée. Je pense que je suis un peu comme un modèle de commande. Voici le coeur du problème. Mon code d'en-tête est quelque chose comme:Simple Question: Passer l'objet avec l'état, C++

class ObjectWithState { 
public: 
    ObjectWithState(int state) { // This constructor creates the problem! 
    state_ = state;  // everyting works with no constructor. 
    } 
private: 
    int state_; 
}; 

class TakesObject { 
public: 
    TakesObject(ObjectWithState obj) { 
    obj_ = obj; 
    } 
private: 
    ObjectWithState obj_; 
}; 

Mes fonctions main() ressemble:

int main() { 
    ObjectWithState some_object(1); 
    TakesObject takes_object(some_object); 
    return 0 
} 

Je reçois l'erreur suivante (g ++):

test.h: In constructor 'TakesObject::TakesObject(ObjectWithState)': 
test.h:14: error: no matching function for call to 'ObjectWithState::ObjectWithState()' 
test.h:5: note: candidates are: ObjectWithState::ObjectWithState(int) 
test.h:3: note:     ObjectWithState::ObjectWithState(const ObjectWithState&) 

Réponse simple?

Je ne sais pas si cela a à voir avec les constructeurs de copie. Si c'est le cas, j'essaie de trouver une solution qui garde la définition de classe de ObjectWithState très propre et courte. Les utilisateurs de cette bibliothèque définiront de nombreuses petites fonctions comme celle qui sera utilisée par la fonction TakesObject. Idéalement, les programmeurs de ObjectsWithState doivent simplement se concentrer sur l'implémentation d'un objet simple. Peut-être que je errantes ...

Répondre

5

Ce que vous pouvez faire est d'utiliser la syntaxe d'initialisation de membre:

class TakesObject { 
public: 
    TakesObject(ObjectWithState obj): obj_(obj) { 
    } 
private: 
    ObjectWithState obj_; 
}; 

Dans votre code affiché, le constructeur TakesObject va d'abord essayer de construire une nouvelle ObjectWithState avec son constructeur par défaut, puis appelez l'opérateur d'affectation pour copier le obj transmis à obj_. L'exemple ci-dessus construit le obj_ directement en utilisant son constructeur de copie.

Vous aurez aussi besoin de définir un constructeur de copie pour votre ObjectWithState classe aussi:

class ObjectWithState { 
public: 
    ObjectWithState(int state) { 
    state_ = state; 
    } 
    ObjectWithState(const ObjectWithState &rhs) { 
    state_ = rhs.state_; 
    } 
private: 
    int state_; 
}; 

Si vous omettez tous les constructeurs de votre déclaration de classe, le compilateur fournit un défaut et un constructeur de copie pour vous. Si vous déclarez constructeurs, le compilateur fournit aucun constructeur par défaut ou copie, donc vous devez implémenter le vôtre.

+1

Bonne réponse, mais il n'a pas besoin de déclarer un constructeur de copie. Le constructeur de copie par défaut est adéquat. – rlbond

+0

Il doit déclarer le constructeur de copie - une fois qu'il a déclaré ObjectWithState (int), le constructeur de copie par défaut a été perdu. –

+0

ObjectWithState() {} ObjectWithState(int state) { state_ = state; } Semble fonctionner. Utiliser la liste d'initialisation nécessite aussi le constructeur const, je pense. Un moyen de simplifier l'ObjectWithState? – Tristan

1

Vous obtenez cette erreur car vous déclarez un constructeur. Le compilateur fournira le constructeur par défaut seulement si vous ne déclarez pas un constructeur dans votre classe. Parce que vous avez déclaré un constructeur, vous n'obtenez pas le constructeur par défaut. Vous devez déclarer explicitement un constructeur sans paramètres.

+0

D'accord, merci.Je suppose qu'il n'y a pas de meilleur moyen de faire cela pour éviter d'avoir à écrire tous ces constructeurs supplémentaires dans ObjectwithState? Je préférerais que ObjectWithState n'ait rien d'autre que l'essentiel. Dois-je être sous-classe et mettre un constructeur par défaut dans la base? Et le constructeur '()' doit-il faire quelque chose? Ou est-ce juste 'ObjectWithState() {} ' – Tristan

+0

Sauf, bien sûr, il ne veut pas de constructeur par défaut. – rlbond

+0

@rlbond La solution de Greg ci-dessus est la façon «plus correcte» de le faire, IMO. Utilisation de l'initialisation avec le constructeur Vous devriez toujours avoir un constructeur de copie de toute façon. Vous ne savez jamais qui va copier votre objet. – jdt141