tutorial smart programar para introduccion inteligentes inteligente ejemplos crear contratos contrato c++ inheritance using private-members public-fields

smart - una forma en c++ para ocultar una función específica



programar contratos inteligentes (10)

¿Por qué no lo haces virtual en la clase base y lo anulas en sus hijos? ( más ayuda )

Tengo una struct A : public B herencia struct A : public B , quiero ocultar funciones individuales de B, ¿es esto posible?

Sé que lo contrario es posible usando el using BMethod en la declaración A.

aclamaciones


Aparte de las formas descritas en las respuestas anteriores (composición, herencia privada y herencia no privada pero con el método heredado declarado privado), otra forma es delete explícitamente el método heredado:

#include <iostream> struct A { void foo() { std::cout << "foo/n"; } }; struct B : A { void foo() = delete; }; int main() { B b; b.foo(); // COMPILER ERROR }

Aunque la llamada b.foo() produce un error de compilación, el código del cliente todavía puede llamar a la versión de la clase base al calificar con el identificador de la clase base A :

b.A::foo(); // compiles, outputs ''foo'' to console

Esta forma de eliminación explícita funciona cuando foo no es un método virtual no eliminado en A Según el estándar C ++ 11 §10.3 / 16, esta eliminación explícita tiene un formato incorrecto cuando el método eliminado en la clase derivada anula un método virtual no eliminado de la clase base. Para obtener más información sobre esta restricción, consulte las respuestas a la pregunta SO C ++ 11 Delete Overriden Method .


Hay otro enfoque más.

class A{ void f1(); void f2(); void f3(); } class BInterface{ void f2(); void f3(); } class B : public A, BInterface { } BInterface b = new B(); b->f1(); //doesn''t work since f1 is not declared in BInterface b->f2(); //should work b->f3(); //should work delete(b);

Utilice BInterface como un filtro para las clases heredadas para excluir métodos indeseables. El principio de sustitución de Liskov no se viola en este caso, ya que un objeto de la clase BInterface no es un objeto de la clase A, aunque un objeto de la clase B sea un objeto de la clase BInterface.


Hay un problema aquí: esto sería una violación directa del Principio de Sustitución de Liskov, a saber, que A ya no actuaría como B

Si desea reutilizar la implementación B , la solución es simplemente hacerlo:

class A { public: void foo() { return b.foo(); } void bar() { return b.bar(); } // ... private: B b; };

No abuses de la herencia, usa la composición en su lugar


La palabra clave de using se puede utilizar para cambiar la visibilidad

struct A { void method1(); }; struct B: public A { void method2(); private: using A::method1; };


No puede "ocultarlo" per se, pero puede hacer que sea un error de compilación llamarlo. Ejemplo:

struct A { void AMethod() {} }; class B : public A { void AMethod() {} //Hides A::AMethod }; int main() { B myB; myB.AMethod(); //Error: AMethod is private static_cast<A*>(&myB)->AMethod(); //Ok return 0; }

Ejemplos en el teclado con el error , y without .

Todo lo dicho, a pesar de que es posible, realmente no deberías hacerlo. Vas a confundir el infierno de los clientes.

EDITAR: Tenga en cuenta que también puede hacer esto con funciones virtuales (y con el error ).


No se puede alterar la visibilidad del método original.

Podría crear un método en la estructura A con el mismo nombre y hacer que ese método sea privado, pero eso no impide que se llame al método cuando una variable de tipo B referencia a una instancia de la estructura A


Para aquellos que sugieren composición ... esta podría no ser la mejor manera de abordar las cosas. Tengo entendido que el Principio de Sustitución de Liskov solo establece que existe la posibilidad de que las funciones de la clase base se usen en el niño, no que necesariamente deban serlo. Por ejemplo, para una clase base particular, puede tener múltiples funciones que esencialmente realizan la misma operación, pero para diferentes casos específicos. En la clase derivada es posible que desee abstraer estas funciones públicas para simplificar la interfaz del usuario. Aquí es donde se puede utilizar la herencia privada. La herencia privada también podría ser una necesidad, si tenemos funciones protegidas en la clase base a las que no queremos que llame el usuario de la clase base, pero sería invaluable para la clase derivada.

En resumen, si TIENE QUE, use herencia privada, pero la composición es la preferida en la mayoría de los casos.


Si desea ocultar selectivamente las funciones de B, no tiene mucho sentido utilizar la herencia pública en primer lugar.
Use la herencia privada y traiga selectivamente los métodos de B al alcance de A:

struct B{ void method1(){}; void method2(){}; }; struct A : private B{ using B::method1; }; A a; a.method1(); a.method2(); //error method2 is not accesible


Si los métodos son privados en B, entonces se mantendrán ocultos incluso si utiliza la herencia pública.