Continuação a linguagem C++

Para uma determinada política, pode haver um número ilimitado de implementações. As implementações de uma política são chamadas de classes de políticas. [2] As classes de política não se destinam ao uso independente; em vez disso, eles são herdados ou contidos em outras classes.
[2] Esse nome é um pouco impreciso porque, como você verá em breve, as implementações de políticas podem ser modelos de classes.
Um aspecto importante é que, diferentemente das interfaces clássicas (coleções de funções virtuais puras), as interfaces das políticas são vagamente definidas. Políticas são orientadas a sintaxe, não orientadas a assinatura. Em outras palavras, o Criador especifica quais construções sintáticas devem ser válidas para uma classe em conformidade, em vez de quais funções exatas a classe deve implementar. Por exemplo, a política do Criador não especifica que Criar deve ser estático ou virtual - o único requisito é que o modelo de classe defina uma função de membro Create. Além disso, o Criador diz que Create deve retornar um ponteiro para um novo objeto (em oposição a must). Conseqüentemente, é aceitável que, em casos especiais, o Create possa retornar zero ou lançar uma exceção.
Você pode implementar várias classes de política para uma determinada política. Todos eles devem respeitar a interface conforme definido pela política. Em seguida, o usuário escolhe qual classe de política usar em estruturas maiores, como você verá.
As três classes de política definidas anteriormente possuem diferentes implementações e até mesmo interfaces ligeiramente diferentes (por exemplo,PrototypeCreator  tem duas funções extras GetPrototyp e SetPrototype).
 However, they all define a function called  Crie com o tipo de retorno requerido, para que eles estejam em conformidade com a política do Criador.
Vamos ver agora como podemos projetar uma classe que explore a política do Criador. Essa classe conterá ou herdará uma das três classes definidas anteriormente, conforme mostrado a seguir:
// Library code template <class CreationPolicy> class WidgetManager : public CreationPolicy {    ... };
As classes que usam uma ou mais políticas são chamadas de hosts ou classes de host. [3] No exemplo acima, WidgetManager é uma classe de host com uma política. Os hosts são responsáveis por montar as estruturas e os comportamentos de suas políticas em uma única unidade complexa.
[3] Embora as classes de host sejam tecnicamente modelos de classe de host, vamos nos ater a uma definição única. Ambas as classes de host e modelos de classe de host atendem ao mesmo conceito.
Ao instanciar o // Application code typedef WidgetManager< OpNewCreator<Widget> > MyWidgetMgr;
Let's analyze the resulting context. Whenever an object of type MyWidgetMgr needs to create a Widget, it invokes Create() for its OpNewCreator<Widget> policy subobject. How ever, it is the user of  1.5.2 Implementando classes de política com funções de membro de modelo
Uma alternativa ao uso de parâmetros de modelo de modelo é usar funções de membro de modelo em conjunto com classes simples. Ou seja, a implementação da política é uma classe simples (em oposição a uma classe de modelo), mas possui um ou mais membros de modelo.
Por exemplo, podemos redefinir a política do Criador para prescrever uma classe regular (sem molde) que expõe uma função de modelo Create<T>. A conforming policy class looks like the following:
struct OpNewCreator {    template <class T>    static T* Create()    {       return new T;    } };

Essa maneira de definir e implementar uma política tem a vantagem de ser melhor suportada por compiladores antigos. Por outro lado, as políticas definidas dessa maneira são mais difíceis de serem discutidas, definidas, implementadas e usadas. 1.6 Enriched Policies
The Creator policy prescribes only one member function, Create. However, PrototypeCreator defines two more functions: GetPrototype and SetPrototype. Let's analyze the resulting context.
Because WidgetManager inherits its policy class and because GetPrototype and Set-Prototype are public members of PrototypeCreator, the two functions propagate through WidgetManager and are directly accessible to clients.  However, WidgetManager asks only for the Create member function; that's all WidgetManager needs and uses for ensuring its own functionality. Users, however, can exploit the enriched interface.
A user who uses a prototype-based Creator policy class can write the following code:
typedef WidgetManager<PrototypeCreator>    MyWidgetManager; ... Widget* pPrototype = ...; MyWidgetManager mgr; mgr.SetPrototype(pPrototype); ... use mgr ...
If the user later decides to use a creation policy that does not support prototypes, the compiler pinpoints the spots where the prototype-specific interface was used. This is exactly what should be expected from a sound design.
The resulting context is very favorable. Clients who need enriched policies can benefit from that rich functionality, without affecting the basic functionality of the host class. Don't forget that users—and not the library—decide which policy class to use. Unlike regular multiple interfaces, policies give the user the ability to add functionality to a host class, in a typesafe manner.

1.7 Destructors of Policy Classes
There is an additional important detail about creating policy classes. Most often, the host class uses public inheritance to derive from its policies. For this reason, the user can automatically convert a host class to a policy and later delete that pointer. Unless the policy class defines a virtual destructor, applying delete to a pointer to the policy class has undefined behavior,[4] as shown below.
[4] In Chapter 4, Small-Object Allocation, you can find a discussion on exactly why this happens.
typedef WidgetManager<PrototypeCreator>    MyWidgetManager; ... MyWidgetManager wm; PrototypeCreator<Widget>* pCreator = &wm; // dubious, but legal delete pCreator;  // compiles fine, but has undefined behavior
Defining a virtual destructor for a policy, however, works against its static nature and hurts performance. Many policies don't have any data members, but rather are purely behavioral by nature. The first virtual function added incurs some size overhead for the objects of that class, so the virtual destructor should be avoided.
A solution is to have the host class use protected or private inheritance when deriving from the policy class. However, this would disable enriched policies as well (Section 1.6).
The lightweight, effective solution that policies should use is to define a nonvirtual protected destructor:
template <class T> struct OpNewCreator {    static T* Create()    {     return new T;

 } protected:    ~OpNewCreator() {} };
Because the destructor is protected, only derived classes can destroy policy objects, so it's impossible for outsiders to apply delete to a pointer to a policy class. The destructor, however, is not virtual, so there is no size or speed overhead.

1.8 Optional Functionality Through Incomplete Instantiation
It gets even better. C++ contributes to the power of policies by providing an interesting feature. If a member function of a class template is never used, it is not even instantiated—the compiler does not look at it at all, except perhaps for syntax checking.[5]
[5] According to the C++ standard, the degree of syntax checking for unused template functions is up to the implementation. The compiler does not do any semantic checking—for example, symbols are not looked up.
This gives the host class a chance to specify and use optional features of a policy class. For example, let's define a SwitchPrototype member function for WidgetManager.
// Library code template <template <class> class CreationPolicy> class WidgetManager : public CreationPolicy<Widget> {    ...    void SwitchPrototype(Widget* pNewPrototype)    {       CreationPolicy<Widget>& myPolicy = *this;       delete myPolicy.GetPrototype();       myPolicy.SetPrototype(pNewPrototype);    } };
The resulting context is very interesting:
• If the user instantiates WidgetManager with a Creator policy class that supports prototypes, she can use SwitchPrototype. • If the user instantiates WidgetManager with a Creator policy class that does not support prototypes and tries to use SwitchPrototype, a compile-time error occurs. • If the user instantiates WidgetManager with a Creator policy class that does not support prototypes and does not try to use SwitchPrototype, the program is valid.
This all means that WidgetManager can benefit from optional enriched interfaces but still work correctly with poorer interfaces—as long as you don't try to use certain member functions of WidgetManager.
The author of WidgetManager can define the Creator policy in the following manner:
Creator prescribes a class template of one type T that exposes a member function Create. Create should return a pointer to a new object of type T. Optionally, the implementation can define two additional member functions—T* GetPrototype() and SetPrototype(T*)—having the semantics of getting and setting a prototype object used for creation. In this case, WidgetManager exposes the

Postagens mais visitadas