Salut.
Les std::make_shared c'est bien mais que se passerait t'il si on a envie de cloner un bouton et si en plus la classe bouton dérive de la classe Widget
A tu prévus un fonction pour
Ne vaudrait t'il pas mieux partir sur un design de ce genre ?
class BaseInterface {
public :
void addChild(Widget* w) {
children.push_back(w);
}
virtual
std::vector<Widget*> getChildren() {
return children;
}
std::vector<Widget*> children;
};
template <typename T>
class Interface : public BaseInterface {
public: using DataType = T;
DataType /* const */ & data() /* const*/{return t_;}
protected:
Interface(T & t) : t_(t){}
const T& clone(const T& i) {
const T* c = new T(i);
return *c;
}
virtual ~Interface(){}
//~Interface(){}
private:
T & t_;
};
class Widget : public BaseInterface {
//Définition de la classe.
virtual void exampleMethod (BaseInterface& bi) {
for (unsigned int i = 0; i < children.size(); i++) {
children[i]->exampleMethod(bi);
}
};
class Button : public Widget, public Interface<Button> {
void exampleMethod(BaseInterface& bi) {
static_cast<Interface<Button>&>(bi).data().exampleMethod().exampleMethod(*this);
}
void exampleMethod(Button &button) {
//Methode definition here.
}
};
En principe tu as 2 interfaces : une de base et une dérivée, ta classe de base hérite de l'interface de base et ta classe dérivée de l'interface dérivée.
Tu peux, dans ton interface de base si tu le veux, définir des widgets enfants, si une action s'applique à un widget parent tu pourra la rappliquer sur les widgets enfants de cette manière.
Dans l'interface enfants tu définis les méthodes de bases des widgets, ici je n'ai défini que la méthode clone, ça évite de devoir définir une méthode clone pour chaque type de widget.
Pour appeler une méthode et la rappliquer sur les widgets enfants, il suffit de définit une méthode dans la classe Widget qui va itérer sur tout les widget enfants, cette méthode doit être virtuelle.
Et dans chaque sous classes, tu redéfinis la méthode en "castant" ton interface, pour récupérer le widget enfant, et appeler ta méthode dessus.
Ce design parait compliqué au 1er abords mais il est puissant, lorsque tu rajouteras un nouveau type de widget, tu n'auras plus à modifier la classe widget.
Tu ne devras la modifier que si tu veux rajouté une méthode dans ta classe Widget que tu veux appliquer à tout tes widgets enfants. (Et je pense que tu pourrait même améliorer ce design avec des pointeurs de fonctions)
Bref..., juste pour te montrer à quel point le c++ est puissant, et, se serait dommage de brider ça puissance avec des shared_ptr.
Personnellement je ne les utilises que lors de la gestion des exceptions dans les bloc try/catch afin que la ressources soit libérée même si une exception est levée.
Ou bien pour les classes non copiable et non dérivée, ils peuvent servir aussi.
Mais pas ailleurs. (Et j'évite de les utiliser le plus possible afin d'éviter de devoir modifier ma classe si, un jour je décide de la rendre copiable ou bien de la faire dériver)
Je pense que SFML utilise pas mal de classe non copiable, Laurent doit sûrement avoir ses raisons car en effet il y a des choses qu'il ne vaudrait pas mieux copié par soucis de performance. (Mais à aucun endroit dans son code je le vois utiliser des shared_ptr et ce genre de chose)
Peut être parce que sa librairie n'utilise pas le c++11 ce qui est dommage mais bon..., en contre partie tu ne dépends pas du shared pointer et tu peux faire dériver ses classes comme tu l'entends et les cloner correctement.
PS : le mot clé auto je ne suis pas très fan non plus et je trouve qu'il sert un peu à rien à part à simplifier l'écriture et éviter de devoir utiliser un typedef dans une méthode. (Mais on pourrait très bien se passé de ce mot clé)
PS 2 : pour les fonctions de calleback j'utilise un delegate pour pouvoir changer la valeur des paramètres de la fonction callback avant son appel, ce qui m'implique de devoir connaître le type de la fonction lorsque je veux changer la valeur de ses paramètres. (Sauf si ce n'est pas une lambda expression ou une fonction anonyme car là le c++ peut déduire le type de la fonction automatiquement lors de la déduction de paramètres template)
Mais en général j'évite d'utiliser les lambda expression qui posent pas mal de problèmes aussi lorsqu'on veut modifier la valeur des paramètres de l'expression.