Salut,
Si la logique entre activate et activate_impl, c'est le pattern NVI, les fonctions virtuelles devraient être privées et c'est bien l'objectif de forcer l'appel à la fonction non virtuelle publique de base et pas celle virtuelle y compris pour B avec une autre instance. Les mêmes raisons qui justifient le NVI vis à vis d'une classe externe les justifient vis à vis d'une autre instance de la même classe (elle agit en tant que client).
Donc, il ne faut pas ajouter de l'amitié mais bien appeler la fonction de base non virtuelle :
virtual void activate_impl(bool is_active) { p_a->activate(is_active);}
Le pattern Decorator - presque plus vieux que le C++[*] - avec le NVI offre en outre la possibilité de bien différencier les aspects décorations des aspects spécialisations (ce qui me fait dire qu'il serait peut être intéressant de creuser ça en article) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
| #include <iostream>
#include <boost\noncopyable.hpp>
class Component : private boost::noncopyable
{
public:
void operation()const
{do_operation();}
virtual ~Component(){}
private:
virtual void do_operation()const=0;
};
class ConcreteComponent : public Component
{
private:
virtual void do_operation()const
{
std::cout<<"ConcreteComponent::do_operation\n";
}
};
class Decorator : public Component
{
public:
Decorator(Component &decorated_)
:decorated(decorated_)
{
}
virtual ~Decorator(){}
protected:
Component const&getComponent()const
{
return decorated;
}
private:
void decorate()const
{
do_decorate();
}
virtual void do_operation()const // ça aurait du sens qu'elle soit 'final' - pour moi qui me suit souvent demandé l'intérêt de ce mot clé, je crois que j'en ai trouvé un :D
{
decorate();
}
virtual void do_decorate()const=0;
Component &decorated;
};
class PreConcreteDecorator : public Decorator
{
public:
PreConcreteDecorator(Component &decorated_)
:Decorator(decorated_)
{
}
private:
virtual void do_decorate()const
{
std::cout<<"a pre decoration\n";
getComponent().operation();
}
};
class PostConcreteDecorator : public Decorator
{
public:
PostConcreteDecorator(Component &decorated_)
:Decorator(decorated_)
{
}
private:
virtual void do_decorate() const
{
getComponent().operation();
std::cout<<"a post decorator\n";
}
};
class NonChainingConcreteDecorator : public Decorator
{
public:
NonChainingConcreteDecorator(Component &decorated_)
:Decorator(decorated_)
{
}
private:
virtual void do_decorate() const
{
std::cout<<"a non chaining decorator\n";
}
};
void call_it(Component &comp_)
{
comp_.operation();
}
int main()
{
ConcreteComponent cc;
std::cout<<"**********\nConcreteComponent : \n";
call_it(cc);
PreConcreteDecorator pre_cc(cc);
std::cout<<"**********\nPreConcreteDecorator : \n";
call_it(pre_cc);
PostConcreteDecorator post_cc(cc);
std::cout<<"**********\nPostConcreteDecorator : \n";
call_it(post_cc);
PostConcreteDecorator post_pre_cc(pre_cc);
std::cout<<"**********\nPostConcreteDecorator(PreConcreteDecorator) : \n";
call_it(post_pre_cc);
NonChainingConcreteDecorator nonchaining_cc(pre_cc);
std::cout<<"**********\nNonChainingConcreteDecorator : \n";
call_it(nonchaining_cc);
NonChainingConcreteDecorator nonchaining_prove_cc(post_pre_cc);
std::cout<<"**********\nNonChainingConcreteDecorator(PostConcreteDecorator(PreConcreteDecorator)) : \n";
call_it(nonchaining_cc);
return 0;
} |
[*]: GoF : 1994 / C++ 'inventé' en 83 mais normalisé en 98
Partager