2011-12-20 16 views
11

Estoy tratando de declarar una matriz con una clase personalizada. Cuando agregué un constructor a la clase, mi compilador se queja de que no hay "ningún constructor que coincida para la inicialización del nombre [3]".¿Cómo declaro una matriz con una clase personalizada?

Aquí está mi programa:

#include <iostream> 

using namespace std; 

class name { 
    public: 
    string first; 
    string last; 

    name(string a, string b){ 
    first = a; 
    last = b; 
    } 
}; 

int main (int argc, const char * argv[]) 
{ 

    const int howManyNames = 3; 

    name someName[howManyNames]; 

    return 0; 
} 

¿Qué puedo hacer para que esta carrera, y qué estoy haciendo mal?

Respuesta

16

Tiene que proporcionar un constructor predeterminado. Mientras estás en ello, fijar su otro constructor, también:

class Name 
{ 
public: 
    Name() { } 
    Name(string const & f, string const & l) : first(f), last(l) { } 
    //... 
}; 

Alternativamente, usted tiene que proporcionar los inicializadores:

Name arr[3] { { "John", "Doe" }, { "Jane", "Smith" }, { "", "" } }; 

Este último es conceptualmente preferible, porque no hay razón para que su clase debería tener una noción de un estado "predeterminado". En ese caso, simplemente tiene para proporcionar un inicializador apropiado para cada elemento de la matriz.

Los objetos en C++ nunca pueden estar en un estado mal definido; si piensas en esto, todo debería quedar muy claro.


Una alternativa es utilizar una dinámica contenedor , aunque esto es diferente de lo que pidieron:

std::vector<Name> arr; 
arr.reserve(3); // morally "an uninitialized array", though it really isn't 

arr.emplace_back("John", "Doe"); 
arr.emplace_back("Jane", "Smith"); 
arr.emplace_back("", ""); 

std::vector<Name> brr { { "ab", "cd" }, { "de", "fg" } }; // yet another way 
+0

POD pueden estar en un estado mal definido;) – fredoverflow

+1

@FredOverflow: No son "mal definidas" - son "sin inicializar", el cual está conceptualmente bien definido, con la semántica de que no debe leerlos. –

+0

Bien, entonces, ¿cuál sería un ejemplo de algo que * puede * estar en un estado mal definido? – fredoverflow

3

Necesita un parameterless constructor para poder crear una instancia de su clase. Su constructor actual requiere dos parámetros de cadena de entrada.

Normalmente C++ implica tener dicho constructor (= constructor sin parámetros predeterminado) si hay no se ha declarado ningún otro constructor. Al declarar su primer constructor con dos parámetros sobrescribe este comportamiento predeterminado y ahora tiene que declarar este constructor de forma explícita.

Aquí está el código de trabajo: (. Por cierto, es necesario incluir para hacer el compilables código)

#include <iostream> 
#include <string> // <-- you need this if you want to use string type 

using namespace std; 

class name { 
    public: 
    string first; 
    string last; 

    name(string a, string b){ 
    first = a; 
    last = b; 

    } 

    name() // <-- this is your explicit parameterless constructor 
    {} 

}; 

int main (int argc, const char * argv[]) 
{ 

    const int howManyNames = 3; 

    name someName[howManyNames]; 

    return 0; 
} 

Una forma alternativa es inicializar las instancias de forma explícita en la declaración

name someName[howManyNames] = { {"Ivan", "The Terrible"}, {"Catherine", "The Great"} }; 
4

Para default-inicializar una matriz de T s, T debe ser construible por defecto . Normalmente, el compilador le da un constructor predeterminado de forma gratuita. Sin embargo, como usted mismo ha declarado un constructor, el compilador no genera un constructor predeterminado.

Sus opciones:

  • añadir un constructor por defecto de nombre, si eso tiene sentido (no creo que sí, pero no sabe el dominio del problema);
  • inicializa todos los elementos de la matriz al declarar (puede hacerlo porque name es un agregado);

    name someName[4] = { { "Arthur", "Dent" }, 
             { "Ford", "Prefect" }, 
             { "Tricia", "McMillan" }, 
             { "Zaphod", "Beeblebrox" } 
            }; 
    
  • uso de un std::vector lugar, y sólo añadir elemento cuando se han construido ellos.

1

sólo tiene que añadir un constructor por defecto a la clase a tener este aspecto:

class name { 
    public: 
    string first; 
    string last; 

    name() { 
    } 

    name(string a, string b){ 
    first = a; 
    last = b; 
    } 
}; 
1

su clase:

class name { 
    public: 
    string first; 
    string last; 

    name() { } //Default constructor. 

    name(string a, string b){ 
    first = a; 
    last = b; 
    } 
}; 

tiene una explícita constructor que requiere dos cuerdas parámetros. Las clases sin un constructor escrito explícitamente obtienen constructores por defecto que no toman parámetros. Agregar el explícito impidió que el compilador generara ese constructor predeterminado por usted.

Por lo tanto, si desea crear una matriz de objetos no inicializados, agregue un constructor predeterminado a su clase para que el compilador sepa cómo crearlos sin proporcionar esos dos parámetros de cadena: consulte la línea comentada arriba.

1

Para crear una matriz de objetos, los objetos necesitan un constructor que no tome ningún parámetro (que crea una forma predeterminada del objeto, por ejemplo, con ambas cadenas vacías). Esto es lo que significa el mensaje de error. El compilador genera automáticamente un constructor que crea un objeto vacío a menos que haya otros constructores.

Si tiene sentido para los elementos de la matriz que se creen vacíos (en cuyo caso, los miembros adquieren sus valores por defecto, en este caso, las cadenas vacías), debe:

-Escribir un constructor vacío:

class name { 
    public: 
    string first; 
    string last; 

    name() { } 
    name(string a, string b){ 
    first = a; 
    last = b; 
    } 
}; 

-O, si no lo necesita, elimine el constructor existente.

Si una versión "vacía" de su clase no tiene sentido, no hay una buena solución para proporcionar parámetros de inicialización a todos los elementos de la matriz en tiempo de compilación. Puede:

  • tener un constructor crear una versión vacía de la clase de todos modos, y una función de init() que realiza la inicialización verdadera
  • Utilice un vector, y en la inicialización crear los objetos e insertarlos en el vector, ya sea usando vector::insert o un bucle, y confía en que no hacerlo en tiempo de compilación no importa.
  • Si el objeto tampoco se puede copiar, puede usar una matriz/vector de punteros inteligentes para el objeto y asignarlos en la inicialización.
  • Si puede usar C++ 11, creo (?) puede usar listas de inicialización para inicializar un vector y comenzarlo (no estoy seguro de si eso funciona con cualquier contructor o solo si el objeto se crea a partir de un único valor de otro tipo). Ej .: .
std::vector<std::string> v = { "xyzzy", "plugh", "abracadabra" }; 

`

Cuestiones relacionadas