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.
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)
.
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;
}
-
Tal vez esto debería hacerse como una nueva pregunta. Llamará más la atención en ese caso.
– navneeth
13 abr 2021 a las 23:55
-
Es porque su constructor es privado, por lo que no se puede crear una instancia desde el
std::make_unique()
llamada de la biblioteca. Estaría bien si su constructor fuera público.– Zenul_Abidín
26 de enero de 2022 a las 10:35
-
En este caso, devuelva std::unique_ptr(new int(0)); estaría permitido. Tengo curiosidad por saber si alguien sabe una forma de evitar tener que usar “nuevo” en este caso, que aparentemente está mal visto en C++ moderno.
– Dale Barnard
3 de mayo de 2022 a las 3:25
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.
-
Tal vez esto debería hacerse como una nueva pregunta. Llamará más la atención en ese caso.
– navneeth
13 abr 2021 a las 23:55
-
Es porque su constructor es privado, por lo que no se puede crear una instancia desde el
std::make_unique()
llamada de la biblioteca. Estaría bien si su constructor fuera público.– Zenul_Abidín
26 de enero de 2022 a las 10:35
-
En este caso, devuelva std::unique_ptr(new int(0)); estaría permitido. Tengo curiosidad por saber si alguien sabe una forma de evitar tener que usar “nuevo” en este caso, que aparentemente está mal visto en C++ moderno.
– Dale Barnard
3 de mayo de 2022 a las 3:25
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