¿Puede un método estático acceder a un método privado de la misma clase?

7 minutos de lectura

Avatar de usuario de Flowing Cloud
Nube que fluye

Tengo esta pregunta debido al constructor singleton/named. En ambos casos, los constructores reales son protegidos o privados, ninguno de los cuales es accesible desde el exterior.

Por ejemplo, un constructor de nombre abreviado es este:

 class A
{
  public:
    static A createA() { return A(0); } // named constructor
  private:
    A (int x);
};
int main(void)
{
   A a = A::createA(); 
}

Pensé que el método estático solo puede acceder a miembros de datos estáticos o acceder a datos/métodos privados a través de un objeto existente. Sin embargo, en el código anterior, constructor privado A() no es estático, y en el momento en que se llama tampoco existe ningún objeto. Entonces, la única explicación que se me ocurre es que el método estático puede acceder al método privado no estático de la misma clase. ¿Alguien puede afirmar o negar mi pensamiento, posiblemente con algunas líneas de explicaciones?

Me disculpo si esto es demasiado trivial, sin embargo, las palabras clave son demasiado comunes y no pude encontrar una respuesta en docenas de páginas de Google. Gracias de antemano.

  • DR; TL; Sí puede.

    – 101010

    25 de agosto de 2016 a las 12:12

  • Supongo que cometió un error tipográfico y quiso decir “Entonces, la única explicación que se me ocurre es que el método estático puede acceder privado no estático método de la misma clase” en lugar de “… estático …”

    – Sander de Dycker

    25 de agosto de 2016 a las 12:17

  • ¡Gracias! ¿Tienes alguna referencia que pueda mirar?

    – Nube que fluye

    25 de agosto de 2016 a las 12:17

  • @SanderDeDycker sí, tienes razón. Voy a corregir ahora.

    – Nube que fluye

    25 de agosto de 2016 a las 12:18

  • ¿Por qué pones una respuesta en la sección de preguntas? Si desea responder su propia pregunta, puede hacerlo, pero póngalo como una respuesta, no como una adición a la pregunta.

    – 463035818_no_es_un_número

    25 de agosto de 2016 a las 14:22

Una función miembro estática tiene los mismos derechos de acceso que una función miembro no estática. Entonces sí, puede acceder a cualquier variable pública, protegida y privada en la clase. Sin embargo, debe pasar una instancia de la clase a la función para que la función pueda acceder al miembro. De lo contrario, una función estática solo puede acceder directamente a cualquier otro miembro estático de la clase.

  • Eso es lo que estoy confundido. En el momento en que llamo al constructor, el objeto ni siquiera existe. Entonces, ¿puede una función estática acceder al constructor privado cuando no existe ninguna instancia?

    – Nube que fluye

    25 de agosto de 2016 a las 12:22

  • @FlowingCloud Consulte a continuación: “La función estática puede acceder a miembros privados, pero aparte de eso, es como cualquier función definida fuera de la clase”. Para ejecutar el constructor, no necesita un objeto. Para cualquier otro método de clase no estático, lo hace.

    – lluvia

    25 de agosto de 2016 a las 12:23


  • En pocas palabras, son las reglas. A mi jefe le gusta decir que una clase siempre es un friend de sí mismo.

    – Fitzwilliam Bennet-Darcy

    25 de agosto de 2016 a las 12:23

  • @FlowingCloud Un constructor es como una función estática. No necesita una instancia porque está creando una instancia, por eso se llama función miembro especial. Así que llamarlo está bien ya que no necesita una instancia.

    – NathanOliver

    25 de agosto de 2016 a las 12:24


  • ¡Gracias a todos! ¡Ahora lo entiendo!

    – Nube que fluye

    25 de agosto de 2016 a las 12:28

Según la norma §11/p2 Control de acceso de miembros [class.access] (Énfasis mío):

Un miembro de una clase también puede acceder a todos los nombres a los que tiene acceso la clase. Una clase local de una función miembro puede acceder a los mismos nombres a los que puede acceder la propia función miembro.113

113) Los permisos de acceso son transitivos y acumulativos para las clases anidadas y locales.

Dado que una función miembro estática es miembro de una clase, tiene acceso a todos los nombres a los que tiene acceso la clase y, en consecuencia, al constructor de la clase misma.

En consecuencia, en tu ejemplo:

class A {
  A(int x);  
public:
  static A createA() { return A(0); } // named constructor  
};

función miembro estática A::createA() tiene acceso a llamar private constructor A::A(int).

Avatar de usuario de Fitzwilliam Bennet-Darcy
Fitzwilliam Bennet-Darcy

Dentro de una función de una clase (incluyendo static funciones), todo el private Se puede acceder a los datos y funciones de los miembros, incluso si se trata de un miembro diferente. instancia de esa clase dentro de esa función.

A menudo explotas esto cuando escribes. copiar constructores y Operadores de Asignación.

(Mi jefe a menudo habla de cómo le gustaría poder deshabilitar este comportamiento usando algún tipo de friend = delete; sintaxis.)

  • No creo que el método estático pueda acceder a un miembro de datos privado sin tener primero un objeto, ¿verdad? Estoy más interesado en saber si el método estático puede acceder a un Método privado (constructor)? // Vi tu explicación arriba. ¡Gracias!

    – Nube que fluye

    25 de agosto de 2016 a las 12:26


  • No, siempre necesitaría un objeto para referirse a un miembro de datos no estático. Pero una función estática puede llamar a una función privada; en tu caso el constructor.

    – Fitzwilliam Bennet-Darcy

    25 de agosto de 2016 a las 12:29

  • Lo siento, solo una pequeña aclaración. ¿Puede una función estática llamar a CUALQUIER función privada, o simplemente al constructor (sin referirse a un objeto)?

    – Nube que fluye

    25 de agosto de 2016 a las 12:35

  • Una función estática solo puede llamar a funciones estáticas o constructores.

    – Fitzwilliam Bennet-Darcy

    25 de agosto de 2016 a las 12:36

  • ¡Entiendo! ¡Gracias!

    – Nube que fluye

    25 de agosto de 2016 a las 12:38

Sí puede. La función estática puede acceder a miembros privados, pero aparte de eso, es como cualquier función definida fuera de la clase. Especialmente, ya que no tiene un this puntero (es decir, no está “vinculado” a ninguna instancia específica), no podrá acceder directamente a ningún miembro (que siempre está “vinculado” a una instancia): si desea hacer eso, necesita una instancia desde algún lugar:

#include <iostream>
using namespace std;

class A
{
  public:
    static A createA() { return A(0); }
    static void dosomething(A *a) { return a->something(); }
  private:
    A (int x) { cout << "ctor" << endl; }
    void something() { cout << "something" << endl; }
};

int main(void)
{
   A a = A::createA(); 
   A::dosomething(&a); 
   return 0;
}

Seguimiento de esto, ¿por qué no está permitido entonces? Si se permite crear un objeto, ¿por qué no se permite crear un puntero hacia él?

using namespace std;
class A
{
  public:
    static std::unique_ptr<A> createA() {
    return std::make_unique<A>(0);
    }
  private:
    A (int x) { y = x;}
    int y;
};
int main(void)
{
   auto a = A::createA(); 
   return 0;
}

Avatar de usuario de Robert Kock
Roberto Kok

Su método estático no accede a ningún miembro estático ni a ningún miembro no estático de una instancia existente.
Es solo crear una nueva instancia.

¿Ha sido útil esta solución?