// globally accessible variable. can be changed at runtime. bool feature_flag = true Class A { std::conditional <feature_flag, UtilityClass, DummyClass> obj_util; A(int x,int y,int z) { } }
3 Réponses :
De quoi s'agit-il de stocker un pointeur vers UtitlityClass
au lieu de la classe elle-même. Préférez un unique_ptr
. Ensuite, si votre drapeau est vrai, créez la classe, sinon vous avez nullptr.
Lorsque vous utilisez la classe, vous devez effectuer des vérifications de nullptr.
Class A { public: A(int x,int y,int z) { if( feature_flag == true ){ // obj_util.reset( new UtilityClass() ); //c++11 // since c++14 obj_util = std::make_unique< UtilityClass >(); } // can be anywhere int class if( obj_util != nullptr ){ obj_util->doStuff(); } } private: std::unique_ptr<UtilityClass> obj_util = nullptr; }
L'auteur avait mentionné qu'il ne pouvait pas utiliser le pointeur dans ce projet
Oops. Oui, vous avez raison. Mais avec les informations dont nous disposons, je pense toujours que c'est une solution viable.
préférez utiliser std :: make_unique code> lors de l'initialisation
std :: unique_ptr <...> code> objet
Oui bien sûr. Mais comme je suis coincé avec un compilateur C ++ 11, il n'y a pas de std :: make_unique. Je changerai la réponse
Si vous ne voulez pas changer obj_util
en pointeur, il serait peut-être raisonnable de le changer en fonction:
class AWrapper { public: AWrapper(bool enabled) { if (enabled) ptr = std::make_unique<A>(); } void print() { ptr->print(); } private: std::unique_ptr<A> ptr; }; bool feature_flag = true; class B { public: B() : obj_util(feature_flag) { if (feature_flag) { // No need to change the syntax obj_util.print(); } } private: AWrapper obj_util; };
Une autre option consiste à créer une classe wrapper, qui réplique l'interface:
class A { public: A() { std::cout << "Constructor"; } void print() { std::cout << "Print"; } }; bool feature_flag = true; class B { public: B() : obj_util(feature_flag) { if (feature_flag) { obj_ptr = std::make_unique<A>(); // Syntax has to be changed to a function call obj_util().print(); } } private: std::unique_ptr<A> obj_ptr; A& obj_util() const { return *obj_ptr; } };
Vous pouvez utiliser quelque chose de similaire à conception basée sur des règles ici. J'implémenterais une classe qui stocke la UtilityClass
basée sur la spécialisation de modèle d'un drapeau booléen:
auto foo() { A<true> t; auto& feature = t.utility; //compiles A<false> t2; auto& feature2 = t2.utility; // does not compile }
Classe A code> peut activer cette fonctionnalité en fonction d'un booléen donné comme paramètre de modèle:
template<bool FeatureActivated> struct A : public Feature<FeatureActivated> {};
Vous pouvez utiliser A
comme ceci: p >
template<bool FeatureActivated> struct Feature; template<> struct Feature<true> { UtilityClass utility; }; template<> struct Feature<false> {};
Voici l'exemple complet: https://godbolt.org/ z / b3Kmo7
Modifier: Cela ne permet pas d'activer ou de désactiver la fonctionnalité pendant l'exécution.
J'aime cette approche, car elle évite les pointeurs comme le PO le suggérait. Mais pour être juste, je pense que c'est une approche compliquée pour résoudre une tâche facile simplement parce que l'OP ne veut pas remplacer obj_util.
par obj_util->
qui est une simple opération de remplacement . La taille de la base de code n'a donc pas d'importance. Il prétend également qu'il est sûr que obj_util
ne sera pas appelé lorsque l'indicateur est faux, donc il pourrait même omettre les vérifications de nullptr (ce que je ne conseillerais pas). Avec une solution comme celle-ci, le code ne devient pas plus lisible car il introduit une complexité inutile. Néanmoins +1 pour l'idée.
Peut-être avez-vous besoin de vérifier à l'exécution dans le constructeur par défaut
UtilityClass
, pour que cela fonctionnera toujours?Comme je l'ai mentionné dans mon article, je ne peux pas toucher UtilityClass. Merci
Si les deux seules options possibles que vous avez (en utilisant des pointeurs et en modifiant la classe) ne peuvent pas être faites (pour des «raisons») alors vous êtes à court d'options. Et à mon avis pas humble du tout, si le
UtilityClass
dépend dufeature_flag
, il aurait dû être conçu et implémenté pour s'assurer qu'il n'échoue pas lors de l'exécution- temps à cause du drapeau, quelle que soit sa valeur.Il semble que vous ayez un problème de conception. Vous devez peut-être diviser
A
en une base (sans les fonctionnalités supplémentaires optionnelles) et une sous-classe (qui les ajoute).@TobySpeight merci. C'est une solution que j'ai en tête.
@Someprogrammerdude convient qu'il s'agit d'un problème de conception que quelqu'un a fait il y a 8 ans, et maintenant nous n'avons pas assez de ressources pour refactoriser ceci :-(