Problema con QObject y QList

Bueno, la cuestión es más bien de teoría de C++ ya que empecé hace muy poco por mi cuenta.
El problema en cuestión:
He definido una clase Asignatura en la que tengo unos atributos para identificar a la asignatura y luego ubicarla en una QTableWidget. Cuando inicio la aplicación, leo de un fichero los datos que necesito para cada asignatura, creo una asignatura y la añado a la QList. El caso es que, cuando acabo de leer todo el fichero, todos y cada uno de los nodos de la lista contienen la misma información.
Según me da a mi la impresión, esto podría ser porque la QList es de punteros a Asignaturas y cuando creo un nuevo objeto antes de insertarlo, en realidad lo que estoy haciendo es cambiar el objeto que ya existía de manera que al final de la ejecución en la QList hay 15 punteros al mismo objeto.La manera en que yo creo una asignatura y la inserto es la siguiente

...
Asignatura *a = new Asignatura (nombre,f,c);
list.append(a);
...

Ese fragmento de código está dentro de un bucle que va leyendo las Asignaturas y luego insertándolas. Cómo podría solucionar esto?

Gracias de antemano!

Resultado

Estuve probando un poco tu código y te dejo una captura del resultado
Imagen alojada en imaXenes.com
Como veras las lista tiene items diferentes.
Lo que hice fue crear un proyecto de consola, crear la clase Asignatura con tres campos (nombre, fila y columna) y el siguiente archivo de texto:
2 3 matematica
2 4 lengua
3 5 ortografia
2 6 aritmetica
2 7 sensacion

Después ejecute y obtuve el resultado de la imagen. Por lo que vi, ese fragmento de código funciona.
Porque no publicas el código de la clase Asignatura, a lo mejor tiene un error.
Y el código para mostrar los datos? No estas usando un model por lo tanto tienes que cargar los datos a mano, a lo mejor el error podría estar ahi.
Saludos!

Clase Asignatura

Esta es mi clase Asignatura:

#include "asignatura.h"
 
//Atributos
QString nombre;
bool aprobada;
double nota, creditos;
int row,col;
 
//Constructor por defecto
//Asignatura::Asignatura(QObject *parent) :
//        QObject(parent)
//{
//}
 
Asignatura::Asignatura(QString nom,int f,int c)
{
    nombre = nom;
    row = f;
    col = c;
}
 
void Asignatura::setNombre(QString n){
    nombre = n;
}
void Asignatura::setAprobada(bool pass){
    aprobada = pass;
}
void Asignatura::setCreditos(double cr){
    creditos = cr;
}
void Asignatura::setNota(double nta){
    nota = nta;
}
void Asignatura::setRow(int r){
    row = r;
}
void Asignatura::setCol(int c){
    col = c;
}
QString Asignatura::getNombre(){
    return nombre;
}
bool Asignatura::getAprobada(){
    return aprobada;
}
double Asignatura::getCreditos(){
    return creditos;
}
double Asignatura::getNota(){
    return nota;
}
int Asignatura::getRow(){
    return row;
}
int Asignatura::getCol(){
    return col;
}

¿Los atributos están definidos dentro de la clase?

Ejemplo:

//Archivo asignatura.h
 
class Asignatura : public QObject
{
 Q_OBJECT
 
 public:
  Asignatura(QObject *parent=0);
 
 // Definicion de metodos y funciones publicas
 
 private:
  QString nombre;
  bool aprobada;
  double nota;
  double creditos;
  int row;
  int col;
}

Lo pregunto porque has comentado la linea del constructor, pero no has comentado las líneas de los atributos de la clase. Si la definición de la clase es como das a entender, esto es, las funciones sí están definidas dentro de la clase pero los atributos están definidos dentro del archivo .cpp sin incluir dentro del ámbito de la clase, entonces el compilador no se quejará y compilará, pero los atributos se considerarán variables 'globales' a la biblioteca y todos los objetos de tipo Asignatura trabajarán sobre las mismas variables, por lo que cada vez que se crea un objeto Asignatura sobreescribe en esas variables y al final el valor de los atributos es el último valor escrito en ellas...

¡Un saludo!

Hecho

Muchas gracias de nuevo por todo.
Ya está solucionado!!

Saludos!

^^

Ok!¡
Pues claramente es eso lo que me pasa. El problema es que no llevo mucho tiempo programando (voy por el segundo curso de informática) y esa es la primera clase que defino en C++. Como verás, los atributos los intenté definir al más puro estilo Java... Entonces, cómo los defino dentro del ámbito de la clase para que sean atributos de esta y no variables globales?

Muchas gracias por la ayuda!

:D

Las clases en C++ se definen el archivo de cabecera (.h) y se implementan en el archivo fuente (.cpp). Este es un ejemplo de clase:

/// Archivo de cabecera: asignatura.h
 
class Asignatura : public QObject
{
 Q_OBJECT
 
 public: //Ambito publico, los metodos y variables definidas aqui son accesibles desde fuera del objeto
 
  Asignatura (QObject *parent=0); //Constructor
 
 QString getNombre() const;              //Metodo GET para el nombre, nos devuelve el nombre de la asignatura
 void setNombre(const QString &n);  //Metodo SET para el nombre, establece el nombre de la asignatura
 
 private: //Ambito privado, los metodos y variables definidas aqui son accesibles sólo desde el interior del objeto
 
  QString nombre; //Atributo nombre de la clase
}

¡Un saludo!

Opciones

Si estas programando en linux, lo mas probable es que te falte instalar algun paquete.
Lo que a mi me pasaba es que me faltaban los paquetes "dev" de Qt. Una vez intalados el depurador funciono de maravillas.
La otra opcion es que publiques el codigo aqui asi lo podemos ver y tratar de llegar a descubrir el problema.

Saludos

Código:

Siento tardar tanto en contestar pero no he tenido tiempo este fin de semana.
Os copio el fragmento de código donde guardo las Asignaturas en la QList:

void MainWindow::initAsignaturas(QString path){
    QFile *in;
    in = new QFile(path);
    in->open(QIODevice::ReadOnly);
 
    QStringList lista;
    QString linea;
    int fila,columna;
    Asignatura *fin;
    for(int i = 0; i < 15 && !in->atEnd();i++){
    linea = in->readLine().trimmed();
    lista = linea.split(" ", QString::SkipEmptyParts);
    bool ok;
    fila = lista.at(0).toInt(&ok,10);
    columna = lista.at(1).toInt(&ok,10);
    //Asignatura fin(lista.at(2),fila,columna);
    fin = new Asignatura(lista.at(2),fila,columna);
    subj.append(fin);
 }
    in->close();
 
}

Dónde puede estar el problema? Tengo claro que tiene que ser algún concepto teórico que desconozco... :S

Depura

En teoría al usar el operador new c++ estar asignando un nuevo espacio de memoria por lo tanto seria improbable que tengas 15 punteros repetidos.

Pero para salir de la duda, inicia un proceso de depuración, pon un punto de ruptura dentro del ciclo.
.En la ventana "Locals and Watchers" de QtCreator puedes validar si todos los objetos de la lista apuntan a direcciones de memoria iguales. Solo busca y expande la QList y observa el valor hexadecimal de cada item (en la columna value) y corrobora que sean distintos.

Fíjate el valor de las variables que vas cargando a las asignaturas, que a lo mejor el error esta ahi.
Prueba y avisa.
Saludos!

Problemas:

No se por qué pero no me funciona el debugger así que no puedo ver qué valores va tomando la QList... No se te ocurre qué puede ser?
Lo que leo del fichero de texto son 2 enteros y un QString simplemente para darle nombre a la asignatura y una posicion en una QTableWidget. Creo el objeto y luego lo añado a la QList... Qué puedo estar haciendo mal?

Gracias por la respuesta!

Anuncios Google