usar usan una sirven que programacion porque para orientada objetos las interfaz interfaces implementacion ejemplos como atributos c++ interface idioms non-virtual-interface

usan - ¿Cómo implementar una clase de interfaz utilizando el idioma de interfaz no virtual en C++?



porque usar interfaces c# (4)

En C ++ una interfaz puede ser implementada por una clase con todos sus métodos puros virtuales.

Dicha clase podría ser parte de una biblioteca para describir qué métodos debe implementar un objeto para poder trabajar con otras clases en la biblioteca:

class Lib::IFoo { public: virtual void method() = 0; };

:

class Lib::Bar { public: void stuff( Lib::IFoo & ); };

Ahora quiero usar la clase Lib :: Bar, así que tengo que implementar la interfaz IFoo.

Para mis propósitos, necesito un conjunto de clases relacionadas, por lo que me gustaría trabajar con una clase base que garantice un comportamiento común utilizando la expresión idiomática NVI:

class FooBase : public IFoo // implement interface IFoo { public: void method(); // calls methodImpl; private: virtual void methodImpl(); };

La expresión de interfaz no virtual (NVI) debería negar a las clases derivadas la posibilidad de anular el comportamiento común implementado en FooBase::method() , pero como IFoo hizo virtual parece que todas las clases derivadas tienen la oportunidad de anular FooBase::method() .

Si quiero usar la expresión idiomática NVI, ¿cuáles son mis opciones además de la fraseología pImpl ya sugerida (gracias espacio-c0wb0y).


Comúnmente, la razón para usar el NVI (a veces también llamado "Método de plantilla") es que las clases derivadas solo deberían cambiar una parte del comportamiento de la clase base. Entonces, ¿qué haces es esto?

class base { public: void f() { // do something derived classes shouldn''t interfere with vf(); // do something derived classes shouldn''t interfere with vg(); // do something derived classes shouldn''t interfere with vh(); // do something derived classes shouldn''t interfere with } private: virtual void vf(); // might be pure virtual, too virtual void vg(); // might be pure virtual, too virtual void vh(); // might be pure virtual, too };

Las clases derivadas pueden conectarse a f() en los lugares a los que están destinadas y cambiar aspectos del comportamiento de f() , sin alterar su algoritmo fundamental.


Creo que tienes tu patrón de NVI en el camino equivocado: http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Non-Virtual_Interface

Sin embargo, no estoy seguro si eso resuelve tu problema.

class IFoo { public: void method() { methodImpl(); } private: virtual void methodImpl()=0; }; class FooBase : public IFoo // implement interface IFoo { private: virtual void methodImpl(); };

Aquí hay un ejemplo de por qué puedes hacer esto usando un lector que lee desde XML y otro desde DB. Tenga en cuenta que la estructura común se traslada al NVI readFromSource, mientras que el comportamiento no común se traslada al privado virtual getRawDatum. De esta forma, el registro y la comprobación de errores solo se necesitan en una función.

class IReader { public: // NVI Datum readFromSource() { Datum datum = getRawDatum(); if( ! datum.isValid() ) throw ReaderError("Unable to get valid datum"); logger::log("Datum Read"); return datum; } private: // Virtual Bits Datum getRawDatum()=0; }; class DBReader : public IReader { private: Datum getRawDatum() { ... } }; class XmlReader : public IReader { private: Datum getRawDatum() { ... } };


Puede ser confuso que una vez que un método se declara como virtual en una clase base, se vuelva virtual en todas las clases derivadas, incluso si las palabras clave virtual no se usan allí. Entonces en tu ejemplo, ambos métodos de FooBase son virtuales.

... negar a las clases derivadas la posibilidad de anular el comportamiento común implementado en FooBase :: method () ...

Si puede deshacerse de IFoo , y simplemente iniciar la jerarquía con FooBase con un method no virtual, eso lo haría. Pero parece que desea permitir que los hijos directos de IFoo anulen el method() , pero para evitar que los hijos de FooBase anulen. No creo que eso sea posible.


Puede usar el lenguaje pimpl para lograr esto:

class IFoo { public: IFoo( boost::shared_ptr< IFooImpl > pImpl ) : m_pImpl( pImpl ) {} void method() { m_pImpl->method(); } void otherMethod() { m_pImpl->otherMethod(); } private: boost::shared_ptr< IFooImpl > m_pImpl; }; class IFooImpl { public: void method(); virtual void otherMethod(); };

Ahora, otros todavía pueden subclasificar IFooImpl y pasarlo a IFoo , pero no pueden anular el comportamiento del method (pueden anular otherMethod ). Incluso puede hacer que IFooImpl una subclase directa de IFoo y usar enable_shared_from_this para inicializar IFoo correctamente. Esta es solo la esencia del método. Hay muchas maneras de modificar este enfoque. Por ejemplo, puede usar el patrón de fábrica para asegurarse de que IFoo s se haya creado correctamente.

Espero que ayude.