teorico programas programacion principiantes practico para funciones ejemplos codigo clases c++ oop

programas - funciones en c++ pdf



c++: diferencia entre funciones miembro y no miembro (6)

¿Cuál es la diferencia entre las funciones miembro y no miembro en c ++?


En el siguiente código, f() es una función miembro de la clase Sample , y g() es una función no miembro:

class Sample { void f(); }; void g();

Es muy sencillo. Dado que f() es un miembro de la clase Sample , entonces su función miembro llamada (de la clase Sample ). Y dado que g() no es miembro de ninguna clase, por lo que se llama función no miembro.


Hay varias diferencias entre una función miembro (que ahora llamaré método ) y una función gratuita (que ahora llamaré función ).

Primero, digamos que no son tan diferentes. El código de objeto generalmente se puede compilar hasta C (o ensamblaje) que son lenguajes de procedimiento sin noción de métodos. Ambos métodos y funciones son llamados como subrutinas.

Ahora que esto está fuera del camino, veamos las diferencias. Se pueden clasificar en dos categorías: conceptual y sintáctica.

Sintácticamente

La sintaxis es la parte obvia de cualquier idioma, por lo que es la más fácil de evitar.

Primera nota: hay dos tipos diferentes de métodos en C ++ (y varios otros lenguajes), los métodos static y los métodos regulares.

Ambos tipos de métodos tienen acceso completo a las clases internas (secciones protected y private ) también (por supuesto) como acceso a la interfaz public la clase.

static métodos static son equivalentes a las funciones de friend (aparte de algunas diferencias de alcance).

Dentro de un método regular, una palabra clave especial ( this en C ++) permite acceder al objeto actual en el que se ha invocado el método (a través de los operadores . , -> .* O ->* ).

Un método regular puede ser const y / o volatile calificado, habilitándolo para (respectivamente) const y / o calificado volatile objetos. Por ejemplo, no se puede llamar a un método no const en un objeto const . Se puede ver que this califica dentro del método, es decir, void Foo::bar() const tiene un this de tipo Foo const* .

Un método regular puede ser marcado como virtual . La virtualidad permite el polimorfismo en tiempo de ejecución al habilitar la anulación. No extenderé este mecanismo aquí, solo notemos que las funciones no pueden ser virtuales.

Un punto a menudo ignorado, es que los métodos (tanto static como regulares) están dentro del alcance de la clase. Esto es importante para la búsqueda de nombres (de otros métodos o atributos / variables) ya que significa que los elementos de la clase tienen prioridad durante la búsqueda de un método en los elementos declarados fuera de la clase.

Ya que la calificación de usar this-> antes de atributo o métodos no es obligatoria, esto es útil en métodos regulares, aunque puede introducir errores sutiles. En métodos estáticos, evita calificar por el nombre de clase los atributos y métodos estáticos a los que uno desea acceder.

Ahora que se han afirmado las principales diferencias sintácticas, verifiquemos las diferencias conceptuales.

Conceptualmente

La POO generalmente consiste en unir el estado y el comportamiento (de este estado). Esto se hace creando clases que agrupan atributos (estado) y comportamiento (métodos) y (en teoría) indicando que solo los métodos pueden actuar sobre el estado. Por lo tanto, en OOP, los métodos son responsables de implementar el comportamiento de la clase.

Los métodos participan en la encapsulación de estado (liberando a los clientes de los detalles de la implementación) y en la preservación de los invariantes de clase (declaraciones sobre el estado de clase que son verdaderas desde su nacimiento hasta su muerte, independientemente de lo que haga con él).

C ++

En C ++, como hemos visto anteriormente, esto se hace utilizando diferentes niveles de acceso ( public , protected y private ) y otorgando acceso a los niveles no public a una parte restringida del código. En general, los atributos serán privados y, por lo tanto, solo serán accesibles a los métodos de clase (y quizás a algunos amigos, por cuestiones de sintaxis).

Nota: le insto a que no use atributos protected , es difícil rastrear sus modificaciones y dado que el conjunto de clases derivadas no tiene límites ... su implementación no se puede cambiar fácilmente después.

Sin embargo, tenga en cuenta que C ++ desalienta la hinchazón de la interfaz con muchos métodos.

El problema es que debido a que los métodos son responsables de mantener invariantes, cuanto más hay y más se difunde la responsabilidad, lo que hace más difícil rastrear errores y garantizar la corrección. Además, como los métodos dependen de las clases internas, hace que el cambio sea más costoso.

En cambio, en C ++, generalmente se recomienda escribir un conjunto mínimo de métodos y delegar el resto del comportamiento a funciones que no sean de friend (siempre que no aumente el costo).

  • Vea la versión de Sutter sobre std::string en Monolith Unstrung .
  • Sutter enfatizó la delegación a los métodos que no son amigos en su Principio de Interfaz en el que afirma que las funciones que se entregan con la clase (en el mismo archivo / mismo espacio de nombres) y usan la clase, son lógicamente parte de la interfaz de la clase. Repite en Excepcional C ++.

Esta respuesta se está volviendo más bien larga, pero sospecho que he pasado por alto las diferencias que otros encontrarían críticas ... bueno, bueno.


Las funciones de miembro se invocan en instancias y tienen un puntero disponible; los no miembros no lo hacen.


Se invoca una función miembro no static en objetos de la clase a la que pertenece. Tiene acceso implícito a this puntero que representa el objeto actual. A través de este puntero, puede acceder a otros miembros fácilmente y con privilegios de acceso completo (es decir, acceder a miembros private ).

Una función no miembro no tiene this implícito. En el ejemplo siguiente, la bar es una función miembro, mientras que la freebar no lo es. Ambos hacen más o menos lo mismo, pero tenga en cuenta cómo la bar obtiene un puntero de objeto implícito a través de this (también solo la bar tiene acceso privilegiado a los miembros de freebar , la freebar solo tiene acceso a los miembros públicos).

class foo { public: void bar() { this->x = 0; // equivalent to x = 0; } int x; }; void freebar(foo* thefoo) { thefoo->x = 1; } // ... foo f; f.bar(); // f.x is now 0 freebar(&f); // f.x is now 1

Semánticamente, una función miembro es más que una función con un parámetro implícito . Está destinado a definir el comportamiento de un objeto (es decir, un objeto de automóvil tendría drive() , stop() como funciones miembro).

Tenga en cuenta que también hay funciones miembro static que tienen privilegios completos pero no obtienen this implícito ni se invocan a través de una instancia de la clase (sino a través del nombre completo de la clase).


Una función miembro (no estática) tiene un argumento implícito, un no miembro no lo tiene.

Sintácticamente, usted pasa ese argumento implícito a la izquierda de la . o -> operator like.so() o like->so() , en lugar de como un argumento de función so( like ) .

Del mismo modo, al declarar una función miembro, debe hacerlo en la clase de la que es miembro:

class Class { public: void a_public_member_function(); };

Las funciones que no son miembros en su lugar se declaran fuera de cualquier clase (C ++ lo llama "en el ámbito del espacio de nombres").

Las funciones miembro (no estáticas) también pueden ser virtuales , pero las funciones no miembros (y las funciones miembro estáticas) no pueden ser virtuales .


Una función miembro se invoca en un objeto y tiene acceso a los campos de la clase.

Las funciones de los miembros pueden ser polimórficas (a través de la palabra clave virtual ) que son esenciales para la POO.