2010-10-05 7 views
5

Entiendo que uno de los beneficios de tener funciones miembro estáticas no es tener que inicializar una clase para usarlas. Me parece que otra ventaja de ellos podría ser no tener acceso directo a las cosas no estáticas de la clase.Uso de la palabra clave "estática" para limitar el acceso en C++ Member Functions

Por ejemplo, una práctica común es si usted sabe que una función tendrá argumentos que no se deben cambiar, simplemente marque esta constante. e.g .:

bool My_Class::do_stuff(const int not_to_be_changed_1, 
         std::vector<int> const * const not_to_be_changed_2) 
{ 
    //I can't change my int var, my vector pointer, or the ints inside it. 
} 

Por lo tanto, es válido usar funciones de miembro estáticas para limitar el acceso. Por ejemplo, digamos que usted tiene una función

void My_Class::print_error(const unsigned int error_no) { 
    switch (error_no) { 
    case 1: 
     std::cout << "Bad read on..." << std::endl; 
     break; 
    //... 
    default: 
     break; 
    } 
} 

Bueno, aquí no vamos a acceder a las variables miembro de la clase. Así que si cambiaba la función a:

static void My_Class::print_error(const unsigned int error_no) { 
    switch (error_no) { 
    case 1: 
     std::cout << "Bad read on..." << std::endl; 
     break; 
    //... 
    default: 
     break; 
    } 
} 

ahora me sale un error, si inadvertidamente intentado acceder a una de mis var privado, etc. (a menos que me pase a mí mismo una instancia de mi clase, lo que haría tener un propósito^_ ^!)

¿Es esta una técnica válida, similar a hacer proactivamente args que no deberían cambiar constantes?

¿Qué inconvenientes podría tener en términos de eficiencia o uso?

Mi principal razón para preguntar es que la mayoría de los tutoriales "estáticos" que leí no mencionaron su uso de esta manera, así que me preguntaba si había una buena razón para no hacerlo, considerando que parece una utilidad herramienta.


Editar 1: Una justificación más lógica de este uso:

I tiene un print_error función, como se describe anteriormente. Podría utilizar un espacio de nombres:

namespace MY_SPACE { 
    static void print_error(...) { 
     ... 
    } 

    class My_Class { 
     .... 
     void a(void) 
    } 
} 

Pero esto es un dolor, porque ahora tengo para alargar TODOS mis declaraciones var, es decir

MY_SPACE::My_Class class_1; 

todos para eliminar una función de mi clase, que, esencialmente, es un miembro de mi clase.

Por supuesto que hay múltiples niveles de control de acceso para las funciones:

//can't change pointer to list directly 
void My_Class::print_error(std::vector<int> const * error_code_list) {...} 

//can't change pointer to list or list members directly 
void My_Class::print_error(std::vector<int> const * const error_code_list) {...} 

//can't change pointer to list or list members directly, access 
//non-const member vars/functions 
void My_Class::print_error(std::vector<int> const * const error_code_list) const {...} 

//can't change pointer to list or list members directly, access 
//non-static member vars/functions 
static void My_Class::print_error(std::vector<int> const * const error_code_list) {...} 

//can't change pointer to list or list members directly, access 
//member vars/functions that are not BOTH static and const 
static void My_Class::print_error(std::vector<int> const * const error_code_list) const {...} 

Seguro que esto es un poco atípica, pero a la disminución de grados por lo que están usando las funciones y variables const const. He visto muchos ejemplos donde las personas podrían haber usado una función const, pero no lo hicieron. Sin embargo, algunas personas piensan que es una buena idea. Conozco a muchos programadores de C++ que no comprenderán las implicaciones de una función const o estática. Del mismo modo, muchos entenderían ambos.

Entonces, ¿por qué algunas personas están tan firmemente en contra de usar esto como un mecanismo de control de acceso si el lenguaje/especificación permite su uso como tal, al igual que con las funciones const, etc.?

+1

Parece extraño tener una función como miembro de una clase si va a denegarle derechos de acceso a los miembros. – JoshD

+2

Una forma mejor de limitar el acceso sería simplemente usar una función que no sea miembro. Aunque no entiendo realmente de qué estás tratando de protegerte. –

+1

Supongamos que tiene una función miembro que usted SABE que no necesita acceder a las variables/funciones miembro en el presente, pero que está relacionada con el trabajo/función de la clase. Conceptualmente, su inclusión en la clase tiene sentido, pero desea asegurarse de que no haya acceso de los miembros de la clase. Por lo tanto, podría convertirlo en una función estática, del mismo modo que crearía una variable que desea impedir el acceso a una variable 'const'. Claro que simplemente no puedes tocar la variable/miembros, y por lo tanto no usar 'const' /' static', pero muchos eligen errar por el lado de la precaución, al menos en el uso de 'const'. –

Respuesta

1

Las funciones de miembro estático se deben usar cuando son relevante para la clase pero no opera en una instancia de la clase.

Los ejemplos incluyen una clase de métodos de utilidad, todos los cuales son estáticos porque nunca necesita una instancia real de la clase de utilidad.

Otro ejemplo es una clase que utiliza funciones auxiliares estáticas, y esas funciones son lo suficientemente útiles para otras funciones fuera de la clase.

+0

Por lo tanto, en función de su respuesta, suena como el caso de uso de ejemplo que originalmente afirmé (una función de impresora de error de ayuda) sería un candidato válido para 'static 'en su mente. –

+0

@Jason: Sí. Por supuesto, creo que prácticamente todas las funciones deben ser miembros de la clase (estáticos o no). Las funciones básicas rompen la función orientada a objetos (aunque me doy cuenta de que las funciones de plantilla que no son miembros son útiles como funciones auxiliares de "pegado"). –

5

Cualquier función miembro debe tener acceso a los otros miembros del objeto. ¿Por qué estás tratando de protegerte de ti mismo?

Los miembros estáticos generalmente se usan con moderación, por ejemplo, los métodos de fábrica. ¿Creará una situación que haga que la siguiente persona que trabaje con su código vaya "WTF ???"

+1

Bueno, diga que tiene una función miembro en la que no necesita acceso a ninguna de sus otras funciones/variables miembros. ¿No sería apropiado entonces limitar ese acceso usando estática? Sé que suena extraño, pero usando el argumento de que puede necesitar el acceso y algún punto cuando el código cambia, podría usarse como un argumento en contra de las constantes en general. –

+4

Con frecuencia quiere protegerse de usted mismo. Esa es la razón por la que existe (o es definitiva, o de solo lectura). Estos modificadores indican la intención y evitan que uses datos de formas que no están previstas. Además, para una función como 'print_error', preferiría convertirla en estática y pasarla en una secuencia de salida y luego usar implícitamente una secuencia de entrada vinculada a un objeto en particular. –

+0

Y en cuanto a la reacción de la siguiente persona que ve su código, si documenta correctamente el código (su razón para hacerlo estático, como se describe anteriormente), sus compañeros de trabajo/colegas deberían comprender. Al igual que con const. Cuando veo una const o una función estática, trato de entender por qué la persona hizo esa distinción.El mejor escenario posible es que dejen la documentación de por qué. –

3

No haga esto. Usar static como un mecanismo de control de acceso es una abominación bárbara.

Una razón para no hacer esto es porque es extraño. Los programadores de mantenimiento tendrán dificultades para entender su código porque es muy extraño. El código que se puede mantener es un buen código. Todo el mundo tiene const métodos. Nadie recibe static-as-const. La mejor documentación para su código es el código en sí. El código de auto-documentación es un objetivo al que debe aspirar. No para que no tenga que escribir comentarios, sino para que ellos no tengan que leer ellos. Porque sabes que no van a hacerlo de todos modos.

Otra razón para no hacer esto es porque nunca se sabe lo que traerá el futuro. Su método print_error anterior no necesita acceder al estado de la clase: ahora. Pero puedo ver cómo algún día podría necesitarlo. Supongamos que su clase es un contenedor alrededor de un socket UDP. En algún momento en el medio de la sesión, el otro extremo cierra la puerta. Quieres saber por qué. Los últimos mensajes que envió o recibió podrían contener una pista. ¿No deberías tirarlo? Necesitas un estado para eso.

Una razón falsa para hacer esto es porque proporciona control de acceso de miembro. Sí, lo hace, pero ya hay mecanismos para esto. Supongamos que está escribiendo una función de la que desea estar seguro de que no cambia el estado del objeto. Por ejemplo, print_error no debería cambiar el estado de ningún objeto. Así que el método const:

class MyClass 
{ 
public: 
    void print_error(const unsigned int error_no) const; 
}; 

...

void MyClass::print_error(const unsigned int error_no) const 
{ 
    // do stuff 
} 

print_error es un método const, lo que significa efectivamente que el puntero es thisconst. No puede cambiar ningún miembro que no sea mutable, y no puede llamar a ningún método que no sea const. ¿No es esto realmente lo que quieres?

+1

+1 por 'bárbaro abominación' – JoshD

+1

Pero, ¿por qué la especificación permite funciones de miembro 'estáticas' en absoluto, si no para tenerlo reservado para funciones auxiliares que no necesitan depender de otros miembros de clase o usar variables de clase (aparte de una biblioteca de funciones auxiliares, tal vez ...)? –

+0

Consulte la descripción anterior de los diferentes niveles de acceso en mi nueva sección titulada "Editar 1". –

1

Es ciertamente correcto decir que las funciones de alcance global, las funciones de miembro estáticas y las funciones de amigo no son del todo ortogonales entre sí. Hasta cierto punto, esto se debe en gran parte a que tienen la intención de tener un significado semántico diferente para el programador, a pesar de que producen un resultado similar.

En particular, la única diferencia entre un método de miembro estático y una función de amigo es que los espacios de nombres son diferentes, el miembro estático tiene un espacio de nombre de ::className::methodName y la función de amigo es ::friendFunctionName. Ambos funcionan de la misma manera.

Bueno, en realidad hay otra diferencia, se puede acceder a los métodos estáticos a través de la indirección del puntero, que puede ser útil en el caso de las clases polimórficas.

Entonces la pregunta es, ¿la función pertenece como "parte" de la clase? si es así, usa un método estático. si no, ponga el método en el alcance global y conviértalo en un amigo si necesita acceder a las variables de miembro privado (o no si no)

Cuestiones relacionadas