Autor
|
Tema: Pasar 'this' como parametro (Leído 3,482 veces)
|
DvNe
Desconectado
Mensajes: 12
|
Buenas, Estoy realizando una clase Tarjeta, la cual tiene el siguiente constructor: #include "tarjeta.h" #include "usuario.h" using namespace std; Tarjeta::Tarjeta (const Numero& numero, const Usuario &user, const Fecha& caducidad) : numero_(numero), user_(&user), caducidad_(caducidad) { Fecha f_actual; titular_ = user.nombre() + " " + user.apellidos(); if (caducidad_ < f_actual) throw(Tarjeta::Caducada(caducidad_)); //(&user).es_titular_de(*this); }
Por otro lado, aquí tenemos la cabecera tarjeta.h #ifndef _TARJETA_H_ #define _TARJETA_H_ #include "fecha.h" #include "cadena.h" #include "numero.h" class Usuario; class Tarjeta { public: class Caducada { public: Caducada (const Fecha& f) : fecha_(f) {} Fecha cuando() const { return fecha_; } private: Fecha fecha_; }; Tarjeta (const Numero&, const Usuario&, const Fecha&); Numero numero() const { return numero_; } Fecha caducidad() const { return caducidad_; } Cadena titular_facial() const { return titular_; } const Usuario* titular() const { return user_; } void anula_titular(); friend std::ostream& operator << (std::ostream&, const Tarjeta&); private: Numero numero_; //Numero de identificacion de la tarjeta const Usuario * const user_; //Puntero constante al usuario dueño Fecha caducidad_; //Fecha de caducidad Cadena titular_; // Nombre y apellidos del dueño Tarjeta (const Tarjeta&);//Deshabilitamos copia de una tarjeta }; #endif
Y por otro lado, los archivos de USUARIO: #ifndef _USUARIO_H_ #define _USUARIO_H_ #include "cadena.h" #include "clave.h" #include "articulo.h" #include "tarjeta.h" #include "numero.h" #include <sstream> //ostringstream #include <map> #include <set> using std::map; using std::set; class Tarjeta; class Usuario { public: //CONSTRUCTOR Y DESTRUCTOR Usuario (const Cadena&, const Cadena&, const Cadena&, const Cadena&, const char*); //~Usuario(); class Id_duplicado { public: Id_duplicado (const Cadena& id) : id_duplicado(id) {} const Cadena idd() { return id_duplicado; } private: const Cadena id_duplicado; }; //FUNCIONES OBSERVADORAS Cadena id() const { return identificador_; } Cadena nombre() const { return nombre_; } Cadena apellidos() const { return apellidos_; } Cadena direccion() const { return direccion_; } Cadena password() const { return password_.clave(); } //FUNCIONES CON TARJETAS typedef map<Numero, Tarjeta*> Tarjetas; void es_titular_de(Tarjeta&); /* void no_es_titular_de(Tarjeta&); const Tarjetas& tarjetas() const; */ //FUNCIONES CON LOS ARTICULOS typedef map<Articulo*, unsigned> Articulos; void compra(Articulo&, unsigned); const Articulos& compra() const { return articulos_; } size_t n_articulos() const { return articulos_.size(); } //SOBRECARGA OPERADOR friend std::ostream& operator << (std::ostream&, const Usuario&); private: Cadena identificador_; Cadena nombre_; Cadena apellidos_; Cadena direccion_; Clave password_; /* Tarjetas tarjetas_;*/ Articulos articulos_; static set<Cadena> identificadores; bool IdValido() const throw(Usuario::Id_duplicado); Usuario (const Usuario&); //Deshabilitamos la copia de un usuario }; void mostrar_carro(std::ostringstream&, const Usuario&); //inline const Tarjetas& tarjetas() const { return tarjetas_; } #endif
El problema es que cada vez que se crea una tarjeta, su constructor, debe asociar al usuario dueño la existencia de dicha tarjeta con la función void es_titular_de(Tarjeta&); Pero no sé hacerlo ya que me sale un error diciendo: pasar ‘const Usuario’ como el argumento ‘this’ de ‘void Usuario::es_titular_de(Tarjeta&)’ descarta a los calificadores
|
|
|
En línea
|
|
|
|
ivancea96
Desconectado
Mensajes: 3.412
ASMático
|
Pon un ejemplo donde falle. Un fragmento de código que falla ayudaría bastante.
|
|
« Última modificación: 2 Abril 2014, 23:01 pm por ivancea96 »
|
En línea
|
|
|
|
amchacon
Desconectado
Mensajes: 1.211
|
No metas clases dentro de otras, aunque sintacticamente se puede (usando el operador de ambito "::") no es adecuado ni una buena costumbre. Te vas a llevar muchos dolores de cabeza innecesariamente. Defina la clase fuera: #include "fecha.h" #include "cadena.h" #include "numero.h" class Usuario; class Caducada { public: Caducada (const Fecha& f) : fecha_(f) {} Fecha cuando() const { return fecha_; } private: Fecha fecha_; }; class Tarjeta { public: Tarjeta (const Numero&, const Usuario&, const Fecha&); Numero numero() const { return numero_; } Fecha caducidad() const { return caducidad_; } Cadena titular_facial() const { return titular_; } const Usuario* titular() const { return user_; } void anula_titular(); friend std::ostream& operator << (std::ostream&, const Tarjeta&); private: Numero numero_; //Numero de identificacion de la tarjeta const Usuario * const user_; //Puntero constante al usuario dueño Fecha caducidad_; //Fecha de caducidad Cadena titular_; // Nombre y apellidos del dueño Tarjeta (const Tarjeta&);//Deshabilitamos copia de una tarjeta }; #endif
|
|
|
En línea
|
|
|
|
DvNe
Desconectado
Mensajes: 12
|
Usuario* pU; pU = new Usuario("pperez","Perico","Perez Palotes","13 Rue del Percebe","pedrofueacomprarpan"); try { const Tarjeta t(numer,*pU,Fecha(6,5,2020)); } catch (Tarjeta::Caducada e) { cerr << "Excepcion: Tarjeta caducada " << e.cuando() <<endl; }
|
|
|
En línea
|
|
|
|
ivancea96
Desconectado
Mensajes: 3.412
ASMático
|
Prueba a poner, en vez de: (&user).es_titular_de(*this);
Pones: user.es_titular_de(*this);
Sinó, prueba a declarar "es_titular_de()" como const. (Siempre que realmente sea const, claro)
|
|
« Última modificación: 3 Abril 2014, 15:09 pm por ivancea96 »
|
En línea
|
|
|
|
eferion
Desconectado
Mensajes: 1.248
|
Tarjeta::Tarjeta (const Numero& numero, const Usuario &user, const Fecha& caducidad) : numero_(numero), user_(&user), caducidad_(caducidad) { Fecha f_actual; titular_ = user.nombre() + " " + user.apellidos(); if (caducidad_ < f_actual) throw(Tarjeta::Caducada(caducidad_)); //(&user).es_titular_de(*this); }
es decir, user tiene el modificador const. La llamada es_titular_de tiene la firma: void es_titular_de(Tarjeta&)
Es decir, no tiene el modificador const. Cuando tu declaras una instancia como const quiere decir que, desde ese momento, no se puede modificar su estado. Esto implica que no se permiten las llamadas a métodos no const para dicha instancia. Hasta ahí tu error. Luego hay varias cosas que no entiendo: 1. es_titular_de no tiene sentido que retorne void, es como preguntar a alguien la hora por la calle, que el otro la vea y no te responda... si lo que hace la implementación es imprimir por pantalla el resultado, mi consejo es que lo saques fuera de la clase. Las razones son sencillas: * La clase que contiene la función se llama Usuario, luego se presupone que su misión es gestionar la información de un usuario y no encargarse además de imprimir sus datos por pantalla, guardar los datos en un fichero y llamar a su novia en los aniversarios... responsabilidades definidas. * Concentrar múltiples responsabilidades conlleva concentrar el código, lo que dificulta las tareas de depuración. * El código se oscurece porque las estructuras de datos tienen a diluirse. Tiene más sentido que la función luzca tal que bool es_titular_de( const Tarjeta& ) const;
2. Tiene sentido crear instancias de "Caducada" con el constructor por defecto?? Entiendo que no, pero sin embargo, al no definir el constructor por defecto en la sección "private" se crea un constructor por defecto. Con poner solo la declaración en el archivo de cabecera vale. En C++11 también puedes impedir el uso del constructor por defecto de la siguiente forma: class Caducada { public: Caducada( ) = delete; };
Lo mismo es aplicable a las clases Tarjeta y Usuario. 3. Esta línea const Usuario * const user_; //Puntero constante al usuario dueño
te puede dar más problemas que alegrías. Sobretodo porque... const Usuario* titular() const { return user_; }
Es decir, no hay ningún problema en que se modifiquen los datos del usuario. Personalmente, dado que no hace falta que la clase cree el puntero, casi es más limpio pasar y almacenar una referencia, así evitas la "tentación" de poner un delete en un momento dado. Además, pasar clases por referencia te asegura de que la clase existe, ya que no se puede pasar un puntero a null por referencia. class Tarjeta { public: Tarjeta (const Numero& numero, const Usuario& usuario, const Fecha& fecha ) : user_( usuario ) { } Usuario& titular() const { return user_; } private: Usuario& user_; };
4.throw(Tarjeta::Caducada(caducidad_));
No es buena idea lanzar una excepción que no herede de std::exception. El motivo es que, si no heredan de std::exception, la captura por defecto es catch( ... ) y en este caso pierdes toda la información acerca de la excepción. Además, siempre es recomendable que la excepción incluya un texto descriptivo... es útil en sistemas más complejos para seguir la traza del fallo. 5.titular_ = user.nombre() + " " + user.apellidos();
Este campo autocalculado no tiene demasiado sentido... nombre() y apellidos() no son llamadas a operaciones costosas, es mejor autocalcular el valor cuando sea necesario, como los puntos anteriores, no es un fallo, solo una cuestión de diseño. 6. Las clases se crean sólo si hay razón para elloclass Id_duplicado { public: Id_duplicado (const Cadena& id) : id_duplicado(id) {} const Cadena idd() { return id_duplicado; } private: const Cadena id_duplicado; };
Vista así, esta clase no aporta nada, parece totalmente prescindible. Bien es cierto que lo ideal es tener el código bien repartido en muchas clases, cada una con una única responsabilidad, y con el menor código posible... pero claro, estas clases tienen que tener una razón de ser y esta, vista así, no lo tiene. Llenar el código de clases inútiles te va a dificultar el mantenimiento de tu código y te va a dar problemas en el futuro... estás avisado.
|
|
|
En línea
|
|
|
|
DvNe
Desconectado
Mensajes: 12
|
A ver ya encontré solución a mi problema pondré todos los ficheros de mi problema ya que hace falta conocer todas las clases para ver el por qué de algunas cosas que apuntas eferion. CLASE USUARIO JUNTO CON SU IMPLEMENTACION#ifndef _USUARIO_H_ #define _USUARIO_H_ #include "articulo.h" #include "tarjeta.h" #include <istream> #include <map> #include <set> using std::map; using std::set; class Tarjeta; #include "cadena.h" class Clave { public: enum Razon {CORTA, ERROR_CRYPT}; class Incorrecta { public: Incorrecta (const Razon& r) : razon_(r) {} Razon razon() const { return razon_; } private: Razon razon_; }; Clave (const char*) throw (Clave::Incorrecta); Cadena clave() const { return pass_cifrada; } bool verifica (const char*); private: Cadena pass_cifrada; }; class Usuario { public: //CONSTRUCTOR Y DESTRUCTOR Usuario (const Cadena&, const Cadena&, const Cadena&, const Cadena&, const Clave&); ~Usuario(); class Id_duplicado { public: Id_duplicado (const Cadena& id) : id_duplicado(id) {} const Cadena idd() const { return id_duplicado; } private: const Cadena id_duplicado; }; //FUNCIONES OBSERVADORAS Cadena id() const { return identificador_; } Cadena nombre() const { return nombre_; } Cadena apellidos() const { return apellidos_; } Cadena direccion() const { return direccion_; } //FUNCIONES CON TARJETAS typedef map<Numero, Tarjeta*> Tarjetas; void es_titular_de(Tarjeta&); void no_es_titular_de(Tarjeta&); const Tarjetas& tarjetas() const { return tarjetas_; } //FUNCIONES CON LOS ARTICULOS typedef map<Articulo*, unsigned> Articulos; void compra(Articulo& articulo, unsigned cant = 1); const Articulos& compra() const { return articulos_; } size_t n_articulos() const { return articulos_.size(); } //SOBRECARGA OPERADOR friend std::ostream& operator << (std::ostream&, const Usuario&); private: Cadena identificador_; Cadena nombre_; Cadena apellidos_; Cadena direccion_; Clave password_; Tarjetas tarjetas_; Articulos articulos_; Cadena password() const { return password_.clave(); } static set<Cadena> identificadores; bool IdValido() const throw(Usuario::Id_duplicado); Usuario (const Usuario&); //Deshabilitamos la copia de un usuario }; std::ostream& mostrar_carro(std::ostream&, const Usuario&); #endif
#include "usuario.h" #include <iostream> #include <iomanip> #include <cstring> #include <cstdlib> #include <unistd.h> using namespace std; Clave::Clave (const char* pass_no_cifrada) throw (Clave::Incorrecta) { if (strlen(pass_no_cifrada) < 5) throw(Incorrecta(CORTA)); srand(time(0)); const char* const validos = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; const char salto[2] = {validos[rand() % 63], validos[rand() % 63]}; if (crypt(pass_no_cifrada,salto) == NULL) throw(Incorrecta(ERROR_CRYPT)); pass_cifrada = crypt(pass_no_cifrada,salto); } bool Clave::verifica(const char* pass) { return (strcmp(pass_cifrada.c_str(), crypt(pass,pass_cifrada.c_str())) == 0); } set<Cadena> Usuario::identificadores; Usuario::Usuario (const Cadena& identificador, const Cadena& nombre, const Cadena& apellidos, const Cadena& direccion, const Clave& pass) : identificador_(identificador), nombre_( nombre), apellidos_(apellidos), direccion_(direccion), password_(pass) { IdValido(); } Usuario::~Usuario() { for (Usuario::Tarjetas::iterator i = tarjetas_.begin(); i != tarjetas_.end(); ++i) (*(*i).second).anula_titular(); identificadores.erase(id()); } bool Usuario::IdValido() const throw(Usuario::Id_duplicado) { pair<set<Cadena>::iterator,bool> i; i = identificadores.insert(id()); if (i.second == false) { throw(Id_duplicado(id())); return false; } else { return true; } } ostream& operator << (ostream& output, const Usuario& user) { output <<"\n" << user.id() << " [" << user.password() << "] " << user.nombre() << " " << user.apellidos() << "\n" << user.direccion() << "\nTarjetas:\n"; for (Usuario::Tarjetas::const_iterator i = user.tarjetas().begin(); i != user.tarjetas().end(); ++i) output << *(*i).second << "\n"; return output; } void Usuario::compra (Articulo& articulo, unsigned cant) { if (cant == 0) articulos_.erase(&articulo); else { if (articulos_.find(&articulo) != articulos_.end()) articulos_.erase(&articulo); articulos_.insert(pair<Articulo*,unsigned>(&articulo,cant)); } } ostream& mostrar_carro(ostream& output, const Usuario& user) { output << "Carrito de compra de " << user.id() << " [Articulos: " << user.n_articulos() << "]\n Cant. Articulo\n=================" << "=========================================\n"; for (Usuario::Articulos::const_iterator p = user.compra().begin(); p != user.compra().end(); p++) output << setfill(' ') << setw(4) << p->second << setw(4) << *p->first << "\n"; return output; } void Usuario::es_titular_de(Tarjeta& t) { tarjetas_.insert(pair<Numero, Tarjeta*>(t.numero(),&t)); } void Usuario::no_es_titular_de(Tarjeta& t) { tarjetas_.erase(t.numero()); }
CLASE TARJETA Y SU IMPLEMENTACION#ifndef _TARJETA_H_ #define _TARJETA_H_ #include "cadena.h" #include "fecha.h" class Usuario; class Numero : public Cadena { public: enum Razon {LONGITUD,DIGITOS,NO_VALIDO}; class Incorrecto { public: Incorrecto (const Razon& r) { razon_ = r; } Razon razon() const { return razon_; } private: Razon razon_; }; Numero (const Cadena&) throw (Numero::Incorrecto); operator const char*() const {return numero_.c_str(); } private: Cadena numero_; static const unsigned LongitudMinima = 13; static const unsigned LongitudMaxima = 19; bool numeroValido() const ; }; bool operator < (const Numero&, const Numero&); class Tarjeta { public: class Caducada { public: Caducada (const Fecha& f) : fecha_(f) {} Fecha cuando() const { return fecha_; } private: Fecha fecha_; }; Tarjeta (const Numero&, const Usuario&, const Fecha&) throw (Tarjeta::Caducada); ~Tarjeta(); Numero numero() const { return numero_; } Fecha caducidad() const { return caducidad_; } Cadena titular_facial() const { return titular_; } const Usuario* titular() const { return user_; } void anula_titular() { user_ = 0; } friend std::ostream& operator << (std::ostream&, const Tarjeta&); private: Numero numero_; const Usuario* user_; Fecha caducidad_; Cadena titular_; }; bool operator < (const Tarjeta&, const Tarjeta&); #endif
#include "tarjeta.h" #include "usuario.h" #include <cstdlib> #include <cstring> #include <iostream> #include <iomanip> using namespace std; Tarjeta::Tarjeta (const Numero& n, const Usuario& user, const Fecha& f) throw (Tarjeta::Caducada) : numero_(n), user_(&user), caducidad_(f) { titular_ = user.nombre() + " " + user.apellidos(); Fecha f_actual; if (caducidad_ < f_actual) { throw(Tarjeta::Caducada(caducidad_));return; } const_cast<Usuario&>(user).es_titular_de(*this); } Tarjeta::~Tarjeta() { Usuario* u = const_cast<Usuario*>(user_); if (u) u->no_es_titular_de(*this); } std::ostream& operator << (std::ostream& output, const Tarjeta& t) { output << "\n " << (const char*) t.numero() << "\n " << t.titular_facial() << "\n Caduca: " << setfill('0') << setw(2) << t.caducidad().mes() << "/" << setw(2) << (t.caducidad().anno() % 100); return output; } Numero::Numero (const Cadena& numero) throw (Numero::Incorrecto) { unsigned i = 0, j = 0, pos = 0; do { pos = i; while (i < numero.longitud() && numero[i] != ' ') { if (isalpha(numero[i])) throw(Incorrecto(DIGITOS)); j++; i++; } numero_ += numero.subcadena(pos,j); j = 0; while (i < numero.longitud() && numero[i] == ' ') { i++; } } while (i < numero.longitud()); if (numero_.longitud() < LongitudMinima || numero_.longitud() > LongitudMaxima) throw(Incorrecto(LONGITUD)); if (!numeroValido()) throw(Incorrecto(NO_VALIDO)); } bool Numero::numeroValido() const { //Algoritmo de Lhun int suma = 0; bool impar = true; for (int i = numero_.longitud() - 1; i >= 0; i--) { if (!impar) { int tmp = (numero_[i] - '0') << 1; //Multiplicamos por 2 si es impar suma += (tmp >= 10) ? tmp - 9 : tmp; } else suma += (numero_[i] - '0'); impar = !impar; } return (suma % 10) ? false : true; } bool operator < (const Numero& numero1, const Numero& numero2) { return atoll(numero1) < atoll(numero2); } bool operator < (const Tarjeta& t1, const Tarjeta& t2) { return t1.numero() < t2.numero(); } std::ostream& operator << (std::ostream& output, const Numero& num) { output << (const char*) num; return output; }
CLASE ARTICULO Y SU IMPLEMENTACION#ifndef _ARTICULO_H_ #define _ARTICULO_H_ #include "cadena.h" #include "fecha.h" class Articulo { public: Articulo (const Cadena&, const Cadena&, const Fecha&, const double&, const unsigned&); Cadena referencia() const { return codigo_Referencia; } Cadena titulo() const { return titulo_; } Fecha f_publi() const { return publicacion_; } double precio() const { return precio_; } unsigned stock() const { return ejemplares_; } double& precio() { return precio_; } unsigned& stock() { return ejemplares_; } friend std::ostream& operator << (std::ostream&, const Articulo&); private: Cadena codigo_Referencia; Cadena titulo_; Fecha publicacion_; double precio_; unsigned ejemplares_; };#endif
#include "articulo.h" #include <iomanip> using namespace std; Articulo::Articulo (const Cadena& ref, const Cadena& title, const Fecha& fecha, const double& price, const unsigned& numero) : codigo_Referencia(ref), titulo_(title), publicacion_(fecha), precio_(price), ejemplares_(numero) {} ostream& operator << (ostream& output, const Articulo& art) { output << "[" << art.referencia() << "] \"" << art.titulo() << "\", " << art.f_publi().anno() << ". " << setprecision(2) << setfill('0') << fixed << art.precio() << "\xE2\x82\xAC"; return output; }
Ahora bien la razón por la que el proyecto tiene esta implementación, es porque es un trabajo para la universidad.
|
|
|
En línea
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
COMO PASAR PARAMETRO DE CRYSTAL REPORTS A VB 6
Programación Visual Basic
|
danieline
|
0
|
4,395
|
26 Octubre 2005, 18:07 pm
por danieline
|
|
|
[SOLUCIONADO] Pasar array como parámetro.
Java
|
NetJava
|
3
|
23,183
|
15 Febrero 2011, 21:55 pm
por Debci
|
|
|
Ayuda: pasar array como parámetro (del objeto)
Java
|
JonaLamper
|
3
|
2,774
|
30 Octubre 2014, 13:27 pm
por ivancea96
|
|
|
Problema al pasar char* como parametro
« 1 2 »
Programación C/C++
|
HardForo
|
12
|
4,581
|
17 Abril 2016, 02:08 am
por HardForo
|
|
|
[Solucionado] Pasar una función como parámetro en C.
« 1 2 »
Programación C/C++
|
NOB2014
|
19
|
12,569
|
25 Septiembre 2016, 17:54 pm
por NOB2014
|
|