c++ - tipos - que es un constructor en c#
¿Por qué se permite explícitamente a los constructores y constructores predeterminados con 2 o más parámetros(no predeterminados)? (4)
De acuerdo con el estándar de codificación C ++ de alta integridad , debe declarar todo el constructor de parámetros senlge como explícito para evitar un uso incidental en las conversiones de tipo . En el caso de que sea un constructor de múltiples argumentos, supongamos que tiene un constructor que acepta múltiples parámetros, cada uno tiene un valor predeterminado, convirtiendo el constructor en algún tipo de constructor predeterminado y también un constructor de conversión:
class C {
public:
C( const C& ); // ok copy
constructor C(); // ok default constructor
C( int, int ); // ok more than one non-default argument
explicit C( int ); // prefer
C( double ); // avoid
C( float f, int i=0 ); // avoid, implicit conversion constructor
C( int i=0, float f=0.0 ); // avoid, default constructor, but
// also a conversion constructor
};
void bar( C const & );
void foo()
{
bar( 10 ); // compile error must be ''bar( C( 10 ) )''
bar( 0.0 ); // implicit conversion to C
}
Entiendo que los constructores con un parámetro (no predeterminado) actúan como convertidores implícitos, que convierten de ese tipo de parámetro al tipo de clase. Sin embargo, explicit
se puede utilizar para calificar cualquier constructor, aquellos sin parámetros (constructor predeterminado) o aquellos con 2 o más parámetros (no predeterminados).
¿Por qué se permite explícitamente en estos constructores? ¿Hay algún ejemplo en el que esto sea útil para evitar algún tipo de conversión implícita?
Probablemente sea solo una conveniencia; no hay ninguna razón para desaprobarlo, entonces, ¿por qué hacer la vida difícil a los generadores de códigos, etc.? Si marcó, las rutinas de generación de código tendrían que tener un paso adicional para verificar cuántos parámetros tiene el constructor generado.
Según various sources , no tiene ningún efecto cuando se aplica a constructores a los que no se puede llamar con exactamente un argumento.
Tal vez fue para mantener el mantenimiento. Al utilizar explicit
en constructores de múltiples argumentos, uno puede evitar la introducción inadvertida de conversiones implícitas al agregar valores predeterminados a los argumentos. Aunque no lo creo; en cambio, creo que es solo que se permiten muchas cosas en C ++ simplemente para no hacer que la definición del lenguaje sea más compleja de lo que ya es.
Quizás el caso más infame es devolver una referencia a variable local no static
. Necesitaría reglas complejas adicionales para descartar todas las cosas "sin sentido" sin afectar a ninguna otra cosa. Entonces solo está permitido, rindiendo UB si usa esa referencia.
O para los constructores, puedes definir cualquier cantidad de constructores predeterminados siempre que sus firmas sean diferentes, pero con más de uno es bastante difícil tener alguno de ellos invocado por defecto. :-)
Una mejor pregunta es, ¿por qué no se permite explicit
también a los operadores de conversión?
Bueno, será, en C ++ 0x. Entonces no había una buena razón por la que no. La razón real para no permitir explicit
a los operadores de conversión podría ser tan prosaica como la supervisión, o la lucha por ser explicit
adoptada en primer lugar, o la simple priorización del tiempo del comité, o lo que sea.
Saludos y hth.,
Una de las razones es porque no duele.
Una razón por la que se necesita es, si tiene argumentos predeterminados para el primer parámetro. El constructor se convierte en un constructor predeterminado, pero aún se puede usar como constructor de conversión
struct A {
explicit A(int = 0); // added it to a default constructor
};
C ++ 0x hace uso real de él para constructores de parámetros múltiples. En C ++ 0x, se puede usar una lista de inicializadores para inicializar un objeto de clase. La filosofía es
si usa
= { ... }
, inicializa el objeto con una especie de "valor compuesto" que conceptualmente representa el valor abstracto del objeto y que desea convertir al tipo.si usa un inicializador
{ ... }
, llame directamente a los constructores del objeto, no necesariamente que desee especificar una conversión.
Considera este ejemplo
struct String {
// this is a non-converting constructor
explicit String(int initialLength, int capacity);
};
struct Address {
// converting constructor
Address(string name, string street, string city);
};
String s = { 10, 15 }; // error!
String s1{10, 15}; // fine
Address a = { "litb", "nerdsway", "frankfurt" }; // fine
De esta manera, C ++ 0x muestra que la decisión de C ++ 03, para permitir explícita en otros constructores, no fue una mala idea.