|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Sep 2003
Messaggi: 9434
|
[C++]: Dati char e string di una classe
Ciao a tutti ragazzi
vorrei un vostro aiuto per capire. Quando ho una classe Notebook con dei membri char vado a definire il costruttore in questo modo Codice:
class Notebook
{
private:
char*modello;
float peso;
float spessore;
float pollici;
public:
Notebook(char*, float, float, float);
virtual void StampaDati()const;
};
Codice:
Notebook::Notebook(char* mod, float ps, float spes, float mon)
{
modello=new char[strlen(mod)+1];
strcpy(modello, mod);
peso=ps;
spessore=spes;
pollici=mon;
}
Codice:
class Notebook
{
private:
string modello;
float peso;
float spessore;
float pollici;
public:
Notebook(string, float, float, float);
virtual void StampaDati()const;
};
vado ad implementare Codice:
Notebook::Notebook(string mod= " ", float ps, float spes, float mon)
{
Modello=mod;
peso=ps;
spessore=spes;
pollici=mon;
}
Se invece avessi una string allocata dinamicamente, come andrebbe implementato il costruttore?
__________________
1)P4 2.4-Asrock p4i65- Sapphire Hd3450 512mb agp- 2GB ddr400-Hd 80gb WD- Thermaltake Litepower 450W 2)Amd 3200-Msi K8n Neo4 Platinum - 2*512 MB pc3200-Asus N6600gt- HD WD 160GB-enermax noisetacker 370. |
|
|
|
|
|
#2 | |
|
Senior Member
Iscritto dal: Jul 2005
Città: Vicenza
Messaggi: 1570
|
Quote:
Codice:
class Notebook
{
private:
string* modello;
float peso;
float spessore;
float pollici;
public:
Notebook(char*, float, float, float);
virtual void StampaDati()const;
};
Codice:
Notebook::Notebook(string &mod, float ps, float spes, float mon)
{
modello = new string(mod);
peso = ps;
spessore = spes;
pollici = mon;
}
Codice:
Notebook::Notebook(string *mod, float ps, float spes, float mon)
{
modello = mod;
peso = ps;
spessore = spes;
pollici = mon;
}
Nel secondo caso l'istanza di stringa è stata già creata quindi tu gli passi solo il puntatore e lo copi ne relativo campo modello (questa seconda versione però te la sconsiglio perchè permette di modificare la stringa modello anche dall'esterno della classe). |
|
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Sep 2003
Messaggi: 9434
|
Grazie mille Kendall del chiarimento
avrei dei dubbi: nell'implementazione non ci vuole una cosa tipo strcpy(modello , char) Codice:
Notebook::Notebook(string &mod, float ps, float spes, float mon)
{
modello = new string(mod); //questa istruzione non crea solo spazio?
strcpy(modello , char)
peso = ps;
spessore = spes;
pollici = mon;
}
e se facessi un ibrido è scorretto? mi spiego: Codice:
class Notebook
{
private:
string* modello;
float peso;
float spessore;
float pollici;
public:
Notebook(string*, float, float, float);
virtual void StampaDati()const;
};
facendo così è come se la stringa fosse statica? Codice:
Notebook::Notebook(string mod=" ", float ps, float spes, float mon)
{
modello = new string(mod);
peso = ps;
spessore = spes;
pollici = mon;
}
__________________
1)P4 2.4-Asrock p4i65- Sapphire Hd3450 512mb agp- 2GB ddr400-Hd 80gb WD- Thermaltake Litepower 450W 2)Amd 3200-Msi K8n Neo4 Platinum - 2*512 MB pc3200-Asus N6600gt- HD WD 160GB-enermax noisetacker 370. |
|
|
|
|
|
#4 | |
|
Senior Member
Iscritto dal: Jul 2005
Città: Vicenza
Messaggi: 1570
|
Quote:
Nel momento stesso in cui ti affidi alla classe string ti astrai da questo tipo di considerazioni (anche se internamente all'implementazione di string vengono utilizzate queste funzioni di basso livello). Nel caso particolare al costruttore di string dai come argomento il valore di "mod" che verrà utilizzato da string per assegnare al tuo campo "modello" una nuova istanza con il valore indicato da mod. |
|
|
|
|
|
|
#5 | ||
|
Member
Iscritto dal: Mar 2008
Messaggi: 47
|
Non vedo distruttori... Se nel costruttore allochi qualcosa con new (o new[]) devi anche deallocarlo con delete (o delete[]) nel distruttore. Inoltre sarebbe meglio usare le liste di inizializzazione.
Codice:
Notebook::Notebook(char* mod, float ps, float spes, float mon)
: modello(0),
peso(ps),
spessore(spes),
pollici(mon)
{
modello = new char[strlen(mod)+1];
strcpy(modello, mod);
}
Notebook::~Notebook()
{
delete [] modello;
}
Quote:
Quote:
Ho detto "dovrebbe" perché non è che sia obbligatorio, ma normalmente è così (per std::string è così di sicuro). |
||
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Come la scriverei io:
Codice:
class Notebook
{
private:
std::string modello;
float peso;
float spessore;
float pollici;
public:
Notebook(const std::string &, float, float, float);
virtual ~Notebook(); //Dato che hai definito un metodo virtuale... In ogni caso un distruttore virtuale male non fa :D
virtual void StampaDati()const;
};
Notebook::Notebook(const std::string & mod, float ps, float spes, float mon) : modello(mod), peso(ps), spessore(spes), pollici(mon)
{ }
|
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Sep 2003
Messaggi: 9434
|
ciao ragazzi
grazie per avermi risposto ovviamente per l'estensione dinamica ci vuole il ditruttore, ma non l'avevo messo poichè non era quello il punto questo comando " std::string " non l'ho mai visto. che cosa fa di preciso? questo è bello, ma se ho appunto un char *........ Codice:
Notebook::Notebook(char* mod, float ps, float spes, float mon)
: modello(0),
peso(ps),
spessore(spes),
pollici(mon)
{
modello = new char[strlen(mod)+1];
strcpy(modello, mod);
}
Notebook::~Notebook()
{
delete [] modello;
}
__________________
1)P4 2.4-Asrock p4i65- Sapphire Hd3450 512mb agp- 2GB ddr400-Hd 80gb WD- Thermaltake Litepower 450W 2)Amd 3200-Msi K8n Neo4 Platinum - 2*512 MB pc3200-Asus N6600gt- HD WD 160GB-enermax noisetacker 370. Ultima modifica di Bandit : 26-07-2012 alle 19:17. |
|
|
|
|
|
#8 |
|
Senior Member
Iscritto dal: Jul 2008
Città: Roma
Messaggi: 542
|
Non è un "comando"
std::string è una classe della libreria standard, usata per istanziare oggetti stringa standard del C++ |
|
|
|
|
|
#9 |
|
Senior Member
Iscritto dal: Jul 2005
Città: Vicenza
Messaggi: 1570
|
Esattamente come dice Lorenzo.
Per dirla in maniera alternativa, l' "std" è il namespace standard che raccoglie tutte le classi standard (per l'appunto). Quindi come tu, in ogni qual caso crei un namespace utilizzi lo specificatore di namespace (il " :: " ) così fai con quello standard (non vi è alcuna differenza alcuna). L'alternativa più comune è quella di includere il namespace con la ben nota dicitura " #include namespace std" Ma come ti è stato detto tutto ciò riguardo solo e semplicemente il sistema di namespace. |
|
|
|
|
|
#10 |
|
Member
Iscritto dal: Jul 2009
Città: Milano
Messaggi: 270
|
La ben nota dicitura non è "using namespace std", o sbaglio?
__________________
AMD PII x4 955 BE | Sapphire HD4850 Vapor-X 1 GB | Samsung SpinPoint F1 500GB | Samsung EcoGreen F4 2TB Gigabyte GA-MA790FXT-UD5P | Fractal Design Define R3 USB3.0 Titanium Grey | CORSAIR 650W CMPSU-650TX Noctua U12P SE2 | 2 x 2GB Kingston 1333 MHz | Samsung SyncMaster P2450 | Samsung SyncMaster T200 |
|
|
|
|
|
#11 | |
|
Senior Member
Iscritto dal: Jul 2005
Città: Vicenza
Messaggi: 1570
|
Quote:
Uops, touchè... Ultimamente mi sto dedicando al C# dove si utilizza sempre l' "#include" (anche se in senso leggermente diverso dal concetto di namespace), da questo l'errore. Hai ovviamente ragione tu |
|
|
|
|
|
|
#12 |
|
Member
Iscritto dal: Jul 2009
Città: Milano
Messaggi: 270
|
La qualità dei tuoi interventi sul forum mi ha fatto pensare che potessi essere io a sbagliarmi e che mi fossi rimbambito, quindi ho messo il punto di domanda.
__________________
AMD PII x4 955 BE | Sapphire HD4850 Vapor-X 1 GB | Samsung SpinPoint F1 500GB | Samsung EcoGreen F4 2TB Gigabyte GA-MA790FXT-UD5P | Fractal Design Define R3 USB3.0 Titanium Grey | CORSAIR 650W CMPSU-650TX Noctua U12P SE2 | 2 x 2GB Kingston 1333 MHz | Samsung SyncMaster P2450 | Samsung SyncMaster T200 |
|
|
|
|
|
#13 |
|
Senior Member
Iscritto dal: Jul 2005
Città: Vicenza
Messaggi: 1570
|
|
|
|
|
|
|
#14 |
|
Senior Member
Iscritto dal: Sep 2003
Messaggi: 9434
|
ok grazie ragazzi
rileggendo il codice di bender Codice:
Notebook::Notebook(char* mod, float ps, float spes, float mon)
: modello(0),
peso(ps),
spessore(spes),
pollici(mon)
{
modello = new char[strlen(mod)+1];
strcpy(modello, mod);
}
mi spiego : con l' inizializzatore :modello(0) nn è lo stesso di mettere Codice:
Notebook::Notebook(string mod= " ", float ps, float spes, float mon) e poi un'altra particolarità Codice:
{
modello = new char[strlen(mod)+1];
strcpy(modello, mod);
}
Codice:
{
modello = new char(mod);
strcpy(modello, mod);
}
__________________
1)P4 2.4-Asrock p4i65- Sapphire Hd3450 512mb agp- 2GB ddr400-Hd 80gb WD- Thermaltake Litepower 450W 2)Amd 3200-Msi K8n Neo4 Platinum - 2*512 MB pc3200-Asus N6600gt- HD WD 160GB-enermax noisetacker 370. Ultima modifica di Bandit : 27-07-2012 alle 12:35. |
|
|
|
|
|
#15 | ||
|
Senior Member
Iscritto dal: Jul 2005
Città: Vicenza
Messaggi: 1570
|
Quote:
modello = 0; oppure modello = NULL; oppure (in c++11) modello = nullptr; Quote:
Il secondo esempio invece è semplicemente errato, in quanto al puntatore a char modello vai ad assegnare un singolo char allocato dinamicamente (tra l'altro char(mod) è un costrutto non valido in quanto non puoi costruire un char da un char* (che sarebbe mod) ). Dopodichè strcpy si troverebbe a copiare una stringa stile c di n caratteri in una puntatore che punta ad un solo carattere, e andresti pertanto in overflow. |
||
|
|
|
|
|
#16 | ||
|
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Quote:
Il codice che utilizza le liste di inizializzazione indica invece che alla variabile locale verrà assegnato il valore 0. Quote:
Ma dato che parliamo di C++ perchè insistere con gli array di char??? |
||
|
|
|
|
|
#17 |
|
Senior Member
Iscritto dal: Sep 2003
Messaggi: 9434
|
ragazzi è perchè non ho mai visto programmi che prevedono l'allocazione di stringhe dinamiche e quindi non so come fare quando si presenta un problema simile
__________________
1)P4 2.4-Asrock p4i65- Sapphire Hd3450 512mb agp- 2GB ddr400-Hd 80gb WD- Thermaltake Litepower 450W 2)Amd 3200-Msi K8n Neo4 Platinum - 2*512 MB pc3200-Asus N6600gt- HD WD 160GB-enermax noisetacker 370. |
|
|
|
|
|
#18 |
|
Senior Member
Iscritto dal: Jul 2005
Città: Vicenza
Messaggi: 1570
|
Le tratti come tratteresti le istanze di una qualsiasi altra classe (visto che di per sè, string è proprio una classe come tutte le altre, solo fa parte della libreria standard)
|
|
|
|
|
|
#19 |
|
Member
Iscritto dal: Mar 2008
Messaggi: 47
|
Esattamente cosa intendo per "stringa dinamica"? In C le stringhe non esistono, quindi si deve ricorrere ad array di caratteri spesso allocati dinamicamente. In C++ invece c'è la classe 'std::string' che non ha quasi mai bisogno di essere allocata dinamicamente (la si dovrebbe usare esattamente come un int o un double).
Se stai seguendo un corso potrebbe essere una buona idea chiedere un chiarimento al professore. Il namespace std contiene tutta la libreria standard del C++. I namespace permettono di dare lo stesso nome a variabili, funzioni, classi... diverse. Ad esempio nella libreria standard c'è la classe 'list' (std::list) che rappresenta una lista. Magari tu vuoi implementare una classe lista che funzioni in maniera diversa. Non puoi chiamarla 'list' dato che il nome è già usato, quindi devi trovare un altro nome; in C la soluzione tipica è quella di aggiungere prefissi: 'Bandit_List', che è terribile. Usando i namespace invece classi in diversi namespace possono avere lo stesso nome: 'std::list', 'bandit::list'. Il vantaggio è che all'interno del namespace 'bandit' puoi usare semplicemente il nome 'list', il compilatore sa che ti stai riferendo alla classe nel namespace corrente. Inoltre se sei sicuro di non usare classi con lo stesso nome puoi importare i nomi di un namespace in quello corrente usando 'using namespace abc;'. Codice:
#include <list> // Definisce std::list.
namespace bandit {
class list...
void t()
{
std::list<int> a;
list<int> b; // Equivalente a bandit::list<int> b.
}
} // fine del namespace bandit
// Qui siamo nel namespace globale (cioè fuori da qualsiasi namespace).
int main()
{
std::list<int> a;
bandit::list<int> b;
using namespace std; // Importa i simboli del namespace 'std' in quello corrente.
list<int> c; // Equivalente a std::list<int> c.
} // Qua termina l'effetto di 'using namespace std;'.
int altro()
{
using namespace bandit; // Importa i simboli del namespace 'bandit' in quello corrente.
list<int> a; // Equivalente a bandit::list<int> a.
}
int ultimo()
{
using namespace std;
using namespace bandit;
list<int> a; // Errore, a quale ti riferisci?
std::list<int> b; // Ok
bandit::list<int> b; // Ok
}
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 16:27.



















