c++ - metodos - ejercicios de constructores en java
¿Cuál es la diferencia entre declarar que un constructor es privado y=eliminar? (7)
Por ejemplo, quiero declarar una clase pero quiero que el cliente no pueda usar el constructor de copia (u operador de asignación de copia)
Los dos siguientes no permiten el uso del constructor de copia:
1.
class Track
{
public:
Track(){};
~Track(){};
private:
Track(const Track&){};
};
2.
class Track
{
public:
Track(){};
~Track(){};
Track(const Track&)=delete;
};
¿Es una de estas formas "más correcta" que la otra o son iguales? ¿Hay algún efecto secundario?
//Does not compile with both the above ways
int main()
{
Track l;
Track p(l);
}
En el primer caso, básicamente está declarando un constructor de copia privada y luego no proporciona ninguna implementación. Al declararlos privados, los no miembros no pueden copiarlo.
En el segundo caso, la sintaxis prohíbe realizar una copia. Esto es C ++ nativo.
La principal diferencia como programador es la legibilidad y la comprensión del código. El primer caso es redundante, por qué declarar el constructor de copia, hacerlo privado y no implementarlo. El cliente tiene que inferir mucho aquí.
Puedes usar "= delete" e implicar claramente lo que estás tratando de hacer.
Hacer que un constructor sea privado fue básicamente un "hack" en el antiguo C ++, ya que era la única forma de evitar que los usuarios los usaran. La capacidad de delete
funciones miembro especiales solo se introdujo en C ++ 11, y es la forma mejor y más idiomática de decir que una clase no se puede copiar. Ya que es explícito acerca de la intención .
Los constructores privados tienen otros usos distintos de prohibir su uso por completo (por ejemplo, pueden ser llamados por funciones de miembro de clase estática). Por lo tanto, hacer que un constructor sea privado no comunica muy bien la intención, y el error resultante tampoco es muy claro.
Hacerlo en privado es la forma "antigua" de hacerlo. El constructor aún existe, pero es privado y solo puede invocarse desde otra función miembro de clase.
= delete
elimina el constructor. No es generado por el compilador, y simplemente no existirá.
Así que lo más probable, = delete
es lo que quieres. (aunque con la advertencia de que no todos los compiladores admiten esta sintaxis todavía, por lo que si la portabilidad es una preocupación ...)
La declaración de un constructor de copia private
aún permite que las funciones miembro de la clase Track
puedan copiar y construir instancias de esa clase, mientras que hacer que se elimine simplemente prohíbe la construcción de copia de ese objeto.
En C ++ 11, eliminar un constructor de copia es la forma correcta de expresar el hecho de que una clase no se puede copiar (a menos que, por supuesto, tenga sentido para usted permitir que las funciones miembro de Track
, o amigos de Track
, construyan y construyan Track
objetos).
Si está en C ++ 11, utilice delete
. La razón es que hace que la llamada sea explícita y la intención clara. Aún puede usar accidentalmente un constructor privado (por ejemplo, en un conjunto restringido de ámbitos), pero el compilador le prohibirá utilizar un constructor eliminado.
Uno de los problemas del constructor privado es que la clase y los amigos aún pueden usarlo, lo que no se traduce en errores de acceso sino en errores de enlace , que pueden ser difíciles de rastrear hasta el sitio de la llamada.
Si las cadenas de herramientas necesarias no son compatibles con los constructores eliminados ( = delete
), no debe definirlo (como se ve en su pregunta); solo debe declararlo y dejarlo sin definir, por ejemplo: private: /n Track(const Track&);
Su primer enfoque no impide que la clase misma se copie a sí misma. La forma tradicional de resolver esto es declarar el constructor de copia como privado y dejarlo sin implementar.
Un problema con eso, sin embargo, es que la intención podría no ser obvia. Alguien que lea el código podría no entender por qué existe una declaración huérfana y podría eliminarla por error. Los comentarios pueden ser de ayuda, como lo sería la herencia privada de boost::noncopyable
si Boost está disponible para usted.
El segundo enfoque hace que la intención sea obvia y es lo que debería preferir si puede usar C ++ 11.
Su primera solución le transmite al lector que el constructor de copias es privado y no se debe utilizar. Su segunda solución solo es válida en C ++ 11. Debido a esto, diría que la implementación más portátil y legible sería su primera, utilizando la propiedad privada.