Προς το περιεχόμενο

C++ new και μπερδεμα


oksosaa

Προτεινόμενες αναρτήσεις

Δημοσ.

Καλησπερα.

 

Μπορεί να μου πεί κάποιος πως μπορώ να φτιάξω πολλά αντικείμενα με την new?

 

class Person{

 

public:

//Person(){name=""}

//destructor

//void setName(string name)

//string getName (void)

.

.

pivate:

string name;

};

 

main()

{

Person *p=new Person;

 

//θελεις να φτιαξω ενα νέο αντικείμενο?

//ναιιιιιιιι

p->setName();

p->getName();

 

}

 

 

Αυτο που θέλω να κάνω είναι:κατα την εκκίνηση του προγράμματος να μην δημιουργείται αυτομάτως ενα νέο αντικείμενο.Δηλαδή θέλω να ρωτήσω αν είναι σωστό

να έχω κατι σαν αυτό:

 

 

 

//θελεις να φτιαξω ενα νέο αντικείμενο?

//ναιιιιιιιι

Person *p=new Person;

p->setName();

p->getName();

 

 

και το άλλο που σκεφτομαι είναι το κάθε νέο αντικείμενο να δημιουργείται μέσα στον constructror κάθε φορά που θα επιλέγω να φτιάξω νέο αντικείμενο.

Δεν ξερω αλλα μαλλον τα λέω λίγο μπερδεμένα.

 

Τέλος πάντων με την new πως μπορω να φτιάξω πολλά αντικείμενα?

Δημοσ.

το ότι τα λες μπερδεμένα είναι γεγονός !!!

 

λοιπόν

============

1) ναι μπορείς να μην ορίζεις το αντικείμενο από την αρχή φαντάσου

ότι η κλάση σου είναι "απλά" ένας τύπος δεδομένων π.χ. int.

2)μπορείς να ζητάς με scanf π.χ. το όνομα από τον χρήστη και να δημιουργείς

το αντικείμενο που θες.Μπορείς την παράμετρο αυτήν να την βάλεις

στον constructor σου ώστε να αποφύγεις την setName μέθοδο.

3)μπορείς να φτιάξεις έναν πίνακα αντικειμένων αν θες να έχεις πολλά και να

τα επεξεργάζεσαι πιο εύκολα.

Δημοσ.

Είναι σωστη όμως προγραμματιστικά αυτη η τακτική?

δηλαδή να μην εχω set και get?

 

class Person{

 

public:

 

Person(string newName)

{

name=newName;

}

 

private:

 

string name;

 

};

 

main()

{

 

cout << "New Object?"

cin >> ans;

while (ans!='n')

{

Person *p=new Person("kiriakos");

}

}

 

 

κατι τέτοιο δηλαδή?

 

 

και κάτι άλλο:

Απο την στιγμή που θα επιλέξω πολλές φορές να δημιουργηθεί αντικείμενο

κάθε αντικείμενο θα καταλαβει ξεχωριστή θέση στη μνήμη έτσι δεν είναι?

δλδ αν επιλεξω 4 φορες δημιουργία νέου αντικειμένου τότε το sizeof(Person)

θα αποθηκευθεί στη μν'ημη 4 φορές ασχετα αν χρησιμοποιώ πίνακα η όχι.

 

 

ευχαριστω

 

 

 

Ειναι μαγκια τροπος ζωης ναρκωτικο που δεν πορεις να αντισταθεις

Δημοσ.
Απο την στιγμή που θα επιλέξω πολλές φορές να δημιουργηθεί αντικείμενο

κάθε αντικείμενο θα καταλαβει ξεχωριστή θέση στη μνήμη έτσι δεν είναι?

 

>
class Object;
Object *obj =new Object();
printf("Address:%p\n",obj);
Object *obj =new Object();
printf("Address:%p\n",obj);
Object *obj =new Object();
printf("Address:%p\n",obj);
Object *obj =new Object();
printf("Address:%p\n",obj);
Object *obj =new Object();
printf("Address:%p\n",obj);

Δημοσ.
Είναι σωστη όμως προγραμματιστικά αυτη η τακτική?

δηλαδή να μην εχω set και get?

 

 

 

 

 

 

κατι τέτοιο δηλαδή?

 

 

και κάτι άλλο:

Απο την στιγμή που θα επιλέξω πολλές φορές να δημιουργηθεί αντικείμενο

κάθε αντικείμενο θα καταλαβει ξεχωριστή θέση στη μνήμη έτσι δεν είναι?

δλδ αν επιλεξω 4 φορες δημιουργία νέου αντικειμένου τότε το sizeof(Person)

θα αποθηκευθεί στη μν'ημη 4 φορές ασχετα αν χρησιμοποιώ πίνακα η όχι.

 

 

ευχαριστω

 

 

 

Ειναι μαγκια τροπος ζωης ναρκωτικο που δεν πορεις να αντισταθεις

 

Από όσο καταλαβαίνω θέλεις κάθε φορά που τρέχει το πρόγραμμα να ορίζεις ένα σύνολο από Person, όχι σταθερού πλήθους. Υπάρχουν διάφοροι τρόποι να το πετύχεις. Οι προχωρημένοι προγραμματιστικά μέθοδοι είναι η χρήση vector ή δυναμικής λίστας, όμως ίσως είναι αρκετά πολύπλοκες για τη χρήση που το θέλεις.

 

Ο τρόπος που προτείνω είναι πίνακας από δείκτες σε αντικείμενα Person με ένα προκαθορισμένο max μέγεθος πχ 10. Αν ορίσεις ένα πίνακα όχι δεικτών αλλά αντικειμένων κατευθείαν, τότε με το που θα δημιουργηθεί ο πίνακας θα τρέξουν 10 constructors απευθείας, και μάλιστα οι no argument, και θα σου δεσμευτεί χώρος για 10 αντικείμενα στη μνήμη. Αν όμως ορίσεις ένα πίνακα 10 δεικτών σε Person, το μόνο που δεσμεύεται είναι μια αμελητέα ποσότητα μνήμης από int. Με τη βοήθεια της for θα δεσμεύεις κάθε φορά μόνο όσα αντικείμενα χρειάζεσαι.

 

Λίγα λόγια για τους constructors/setters-getters. Υπάρχουν 3 τρόποι να δώσεις τιμές στις ιδιότητες (μεταβλητές) ενός αντικειμένου.

1. Με τον default - no argument constructor - θα δίνει την προεπιλεγμένη τιμή που έχει οριστεί στον κώδικα του no argument constructor

>Person x;

 

2. Με custom constructor

>Person x("mitsoulas");

 

3. Με συνάρτηση τύπου getter

>Person x; // το αντικείμενο έχει δημιουργηθεί κάπου πιο πριν στον κώδικά μας
x.setName("mitsoulas");

 

Δες ένα παράδειγμα ενός πλήρους αντικειμένου Person με ορισμένες αυτές τις συναρτήσεις συν μια print που απλά τυπώνει το περιεχόμενο του name.

Τις συναρτήσεις μέλη της κλάσης τις περιγράφω εκτός της κλάσης.

 

>#include <iostream>
using namespace std;

class Person{
   private:
       string name;
   public:
       Person();
       Person(string);
       void setName(string);
       void print() const;
};

Person::Person(): name("Undefined") { }

Person::Person(string _name): name(_name) { }

void Person::setName(string _name)
{
   name = _name;
}

void Person::print() const
{
   cout << name << endl;
}

int main()
{
   Person x;
   x.print();
   
   Person y("Yname");
   y.print();
   
   Person z;
   z.setName("Zname");
   z.print();
   
   cin.get(); //pause
   return 0;    
}

 

Ό,τι δεν σου είναι αρκετά κατανοητό με ρωτάς.

 

Συνέχεια στο επόμενο Post...

 

---------- Προσθήκη στις 01:37 ---------- Προηγούμενο μήνυμα στις 00:47 ----------

 

Υλοποίηση με πίνακα από δείκτες σε Person. Προσοχή: Μέσα στην κλάση δεν χρησιμοποιούμε δυναμική δέσμευση μνήμης, μόνο στον πίνακα μέσα στη main. Η κλήση των συναρτήσεων μελών σε δυναμικά ορισμένα αντικείμενα γίνεται με τον τελεστή βέλος (->) και όχι με τον τελεστή τελεία (.) όπως συνήθως.

 

>#include <iostream>
using namespace std;

const int MAX = 10; //Max Persons in array


class Person{
   private:
       string name;
   public:
       Person();
       Person(string);
       void setName(string);
       void print() const;
};

Person::Person(): name("Undefined") { }

Person::Person(string _name): name(_name) { }

void Person::setName(string _name)
{
   name = _name;
}

void Person::print() const
{
   cout << name << endl;
}

int main()
{
   Person *Array[MAX];
   Person *tempPerson;
   string tempName;
   int i,N;
   
   do {
       cout << "How many Persons? (Max " << MAX << "): ";
       cin >> N;
       cin.ignore();
   } while (N<1 || N>MAX);
   
   for (i=0;i<N;i++)
   {
       cout << "Name of Person " << i+1 << ": ";
       getline(cin,tempName);
       tempPerson = new Person(tempName);
       Array[i] = tempPerson;
       tempPerson = NULL;
       delete tempPerson;
   }
   
   for (i=0;i<N;i++)
       Array[i]->print();
           
   cin.get(); //pause
   return 0;    
}

 

Μέσα στην επανάληψη, η προσωρινή μεταβλητή δεσμεύει μνήμη και δείχνει σε αυτήν. Με την ισότητα κάνουμε την επιθυμητή θέση του πίνακα να δείχνει στην δεσμευμένη μνήμη του temp. Τέλος, βάζουμε το temp να δείχνει στο κενό πριν το διαγράψουμε, ώστε να μη διαγραφεί η μνήμη που δεσμεύσαμε πριν και πλέον χρησιμοποιείται από τον πίνακα. Μετά τη διαγραφή, η επανάληψη μπορεί να δεσμεύσει εκ νέου μνήμη για την temp και να συνεχιστεί η ίδια διαδικασία.

 

Μπορείς να με ρωτήσεις αναλυτικά ό,τι δεν κατανοείς. Ελπίζω να βοήθησα.

Δημοσ.

Top_Gear σε ευχαριστώ που είσαι τόσο αναλυτικός.

 

Να σου πώ πως δεν είμαι άσχετος απο προγραμματισμό και όλα όσα μου εχετε πει έως τώρα τα καταλαβαίνω.

 

Απο εκεί και πέρα επειδη έχω κουραστεί να στείνω προγραμματάκια μιας χρήσης που είναι και κλαϊν μαϊν προσπαθώ να μάθω να προγραμματίζω σωστα.

 

Γνωρίζω απο conteiners κ.τ.λ απλά είπα να ξεκινήσω να κάνω μία επανάληψη απο την αρχή.

 

Αν έχεις κάποιο site σχετικό με το πώς να γράφουμε τα προγράμματα μας μόνο ( oxi UML κ.τ.λ ) καλό θα ήταν να το έβλεπα.

 

Δηλαδή δέν πρέπει να γίνεται δέσμευση μνήμης μέσα στην κλάση μου έτσι?

Και αποδέσμευση μνήμης ( delete Person ) δεν πρέπει να γίνεται μέσα στον destructor?

Δημοσ.
Top_Gear σε ευχαριστώ που είσαι τόσο αναλυτικός.

 

Να σου πώ πως δεν είμαι άσχετος απο προγραμματισμό και όλα όσα μου εχετε πει έως τώρα τα καταλαβαίνω.

 

Απο εκεί και πέρα επειδη έχω κουραστεί να στείνω προγραμματάκια μιας χρήσης που είναι και κλαϊν μαϊν προσπαθώ να μάθω να προγραμματίζω σωστα.

 

Γνωρίζω απο conteiners κ.τ.λ απλά είπα να ξεκινήσω να κάνω μία επανάληψη απο την αρχή.

 

Αν έχεις κάποιο site σχετικό με το πώς να γράφουμε τα προγράμματα μας μόνο ( oxi UML κ.τ.λ ) καλό θα ήταν να το έβλεπα.

 

Δηλαδή δέν πρέπει να γίνεται δέσμευση μνήμης μέσα στην κλάση μου έτσι?

Και αποδέσμευση μνήμης ( delete Person ) δεν πρέπει να γίνεται μέσα στον destructor?

 

Ωραία, πολύ καλό αυτό. Μέσα στην κλάση θα μπορούσε να γίνει δυναμική δέσμευση αν πχ. ήθελες κάθε αντικείμενο να έχει ένα πίνακα παρόμοιο με αυτό στην main, ή χρησιμοποιούσες πιο πολύπλοκες δομές δεδομένων. Αυτό όμως είναι αρκετά επίφοβο στη διαχείριση. Δηλαδή σε ένα αντικείμενο που περιέχει δυναμικά δεσμευμένες μεταβλητές χρειάζεται προσοχή στο delete μέσα στο destructor: πρέπει να κάνεις delete variable και αμέσως μετά να την κάνεις = NULL (σε περίπτωση που ξεχαστείς και την χρησιμοποιήσεις πάλι να μην καταστρέψει τα καινούρια περιεχόμενα μνήμης που θα περιέχονται εκεί που έδειχνε πριν).

 

Επίσης δεν ξέρω αν γνωρίζεις για τον copy constructor. Ο default copy constructor χρησιμοποιείται κάθε φορά που κάνεις αντιγραφή ενός αντικειμένου σε ένα άλλο (πχ y=x; όπου y,x Persons) και κάνει ένα ρηχό αντίγραφο του x στο y. Δηλαδή κάνει μία προς μία αντιγραφή τις τιμές των μεταβλητών του x στο y. Σε περίπτωση που έχεις δυναμικά δεσμευμένες μεταβλητές, αν δεν αλλάξεις τον copy constructor θα έχεις το εξής αποτέλεσμα: το y->name θα πάρει την τιμή του x->name. Η τιμή όμως είναι η θέση μνήμης στην οποία δείχνει, άρα θα έχεις 2 αντικείμενα να δείχνουν στο ίδιο σημείο μνήμης. Αυτό δεν είναι απλά άστοχο αλλά καταστροφικό, γιατί φαντάσου να κάνεις διαγραφή του ενός, και το άλλο να πάει να αλλάξει τιμή στη θέση μνήμης που θα χρησιμοποιείται από κάτι άλλο. Εκεί πρέπει να φτιάξεις δικό σου copy constructor και να δεσμεύσεις νέα μνήμη για το καινούριο αντικείμενο.

 

Δεν έχω να σου προτείνω site για να μάθεις προγραμματισμό, παρά μόνο για να συμβουλεύεσαι τη σύνταξη εντολών και τεχνικών που δεν θυμάσαι. Αν πραγματικά θέλεις να ασχοληθείς με σύνταξη μεγάλων προγραμμάτων χρειάζεσαι ένα καλό βιβλίο.

 

Αν θέλεις να ασχοληθείς έντονα σου προτείνω αυτό

http://www.ebooks.gr/book/11710

από τον δημιουργό της c++. Θα σε απασχολήσει για αρκετές εβδομάδες.

 

Αν ψάχνεις κάτι πιο προσιτό από θέμα ταχύτητας και δυσκολίας

http://books.phigita.net/isbn/9789605123185

 

Στον προγραμματισμό ό,τι δώσεις παίρνεις, οπότε να ξέρεις πως τίποτα δεν πάει χαμένο όσο ασχολείσαι. Καλή μελέτη!

Δημοσ.

 

>#include <iostream>
using namespace std;

const int MAX = 10; //Max Persons in array


class Person{
   private:
       string name;
   public:
       Person();
       Person(string);
       void setName(string);
       void print() const;
};

Person::Person(): name("Undefined") { }

Person::Person(string _name): name(_name) { }

void Person::setName(string _name)
{
   name = _name;
}

void Person::print() const
{
   cout << name << endl;
}

int main()
{
   Person *Array[MAX];
   Person *tempPerson;
   string tempName;
   int i,N;
   
   do {
       cout << "How many Persons? (Max " << MAX << "): ";
       cin >> N;
       cin.ignore();
   } while (N<1 || N>MAX);
   
 [b]  for (i=0;i<N;i++)
   {
       cout << "Name of Person " << i+1 << ": ";
       getline(cin,tempName);
       tempPerson = new Person(tempName);
       Array[i] = tempPerson;
       tempPerson = NULL;
       delete tempPerson;
   }
   
   for (i=0;i<N;i++)
       Array[i]->print();
    [/b]       
   cin.get(); //pause
   return 0;    
}

ΤΙ ακριβος κανεις εδω? Delete το 0 ?

Δημοσ.
ΤΙ ακριβος κανεις εδω? Delete το 0 ?

 

Δεν είναι αναγκαίο, απλά μερικοί παλιοί compilers ενδέχεται να χτυπήσουν αν κάνεις δεύτερο new χωρίς delete πριν.

Δημοσ.

Το εκανες debug και σου βγαζει αποτελεσμα? Στην ουσια κανεις το παρακατω

>int _tmain(int argc, _TCHAR* argv[])
{
class foo{public: int fee;};
//1
printf("%d",((foo*)0)->fee);
//kai 2
delete ((foo*)0);
return 0;
}

Δημοσ.

Καλησπερα και πάλι παλουκαρια.

 

Να σας ρωτήσω...

 

Δεν θα είναι καλύτερα να φτιάξω μια νέα κλάση η οποία θα διαχειρίζεται τα αντικείμενα?

Δηλαδή κάθε φορα που θα θέλω νέο αντικείμενο να καλώ την "πάνω" κλάση ( abstract ειναι δεν ξέρω ενημερώστε με.. ) έτσι ώστε να επιστρέφει κάποια μέθοδος ένα νέο αντικείμενο της κάτω κλάσης.

 

Είναι σωστο αυτό προγραμματιστικά??

 

thanks!

Δημοσ.
Καλησπερα και πάλι παλουκαρια.

 

Να σας ρωτήσω...

 

Δεν θα είναι καλύτερα να φτιάξω μια νέα κλάση η οποία θα διαχειρίζεται τα αντικείμενα?

Δηλαδή κάθε φορα που θα θέλω νέο αντικείμενο να καλώ την "πάνω" κλάση ( abstract ειναι δεν ξέρω ενημερώστε με.. ) έτσι ώστε να επιστρέφει κάποια μέθοδος ένα νέο αντικείμενο της κάτω κλάσης.

 

Είναι σωστο αυτό προγραμματιστικά??

 

thanks!

 

Μάλλον το uml δεν είναι τόσο ασήμαντο όσο νομίζεις ;)

 

Evgenios->Την τεχνική την είδα σε ένα βιβλίο του Jesse Liberty. Εμένα μου λειτουργεί. Αν τυχόν κάνω λάθος θα το κοιτάξω μόλις ξαναπάω βιβλιοθήκη.

Δημοσ.

Oκ δεν είπα πως το uml είναι ασήμαντο , αντιθετα πρώτα απο αυτά πρεπει να ξεκινας και προς το τέλος να γράψεις τον κώδικα αν ακολουθείς μοντέλα ανάπτυξης λογισμικου R.U.P , καταράκτη , XP κ.τ.λ

 

Απλά τώρα θέλω να ασχοληθώ αποκλειστικά με κώδικα και ομολογώ πως αυτό με έβγαλε λίγο απο τον σκοπό μου.

 

ΟΚ top_gear thanks!

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.

  • Δημιουργία νέου...