Εμφάνιση 1-9 από 9
  1. #1
    Εγγραφή
    04-02-2009
    Ηλικία
    33
    Μηνύματα
    1.486
    Downloads
    4
    Uploads
    0
    Τύπος
    ADSL
    Ταχύτητα
    2048/256
    ISP
    Cyta Hellas
    Καλησπέρα, θέλω να κάνω μια ερώτηση για ένα θέμα στη C++ που ούτε ξέρω πως να το περιγράψω.

    Έχω κάνει subclass την QPushButton εξής:
    Κώδικας:
    class PushButton : public QPushButton
    {
    public:
            PushButton() = default;
            PushButton(QWidget* parent);
            //Copy constructor
            PushButton(const PushButton& other);
            //Copy assignement
            PushButton& operator=(const PushButton& other);
    private:
            //Nothing
    }
    Τώρα η υλοποίηση των copy ctors + assignement operator πως θα είναι; Ρωτάω γιατί το this και other δεν έχουν private member να κάνουμε swap.

    Κώδικας:
    PushButton::PushButton(const PushButton& other)
            : QPushButton(new QPushButton())    //copy ctor is deleted for QPushButton
    {
            this->?? = other.???
    }
    Αντίστοιχη είναι η ερώτηση και για τον assignement operator.
    Κώδικας:
    PushButton& operator(const PushButton& other)
    {
            if(this != &other)
            {
                    std::swap(this, &other); //Fancy error
            }
    }
    1. Ξέρει κανείς πως υλοποιείται ο κανόνας των 0/3/5 σε τέτοια περίπτωση; Αποκλείω την περίπτωση για default ή deleted ctors γιατί θέλω όντως να το υλοποιήσω και να δω πως γίνεται.

    2. Όπως πάνω, στη περίπτωση που κάποιος ctor της base κλάσης είναι μη διαθέσιμος, πως το χειριζόμαστε; Τον προσπερνάμε με μια new SomeType() απλά για περάσει στο compilation;

    Ευχαριστώ για το χρόνο σας.
    Τελευταία επεξεργασία από το μέλος petran_18 : 28-12-20 στις 23:48.
    Με ΜΑΤ και βία δεν βγαίνει πανδημία, Μιχαλάκη και Κούλη.

  2. #2
    Εγγραφή
    13-11-2011
    Περιοχή
    Χολαργός
    Ηλικία
    37
    Μηνύματα
    1.438
    Downloads
    1
    Uploads
    0
    Τύπος
    VDSL2
    Ταχύτητα
    24000 / 4500
    ISP
    Wind
    DSLAM
    Wind - ΧΟΛΑΡΓΟΣ
    Path Level
    Interleaved
    Χωρίς να είμαι ειδικός επί του θέματος (έχω χρόνια να ασχοληθώ με C++), δεν σε ενδιαφέρουν μόνο τα private members.

    Στο Copy Constructor, Desctructor κτλ θα κάνεις τις δουλειές που χρειάζεται για να κάνεις copy/destruct. Πχ στον copy, αντιγράφεις όλα τα private/protected/public members, φτιάχνεις καινούργια references κτλ. Οπότε αφού δεν έχεις τίποτα να κάνεις copy/destruct αλλά θέλεις να τα ορίσεις, τότε απλά τα ορίζεις και καλείς τα αντίστοιχα base, αν υπάρχουν, αλλιώς τα αφήνεις άδεια.

    Όσων αφορά την QT, τότε σύμφωνα με το documentation δεν επιτρέπεται το copy γιατί μπορεί να έχει ανεπιθύμητα αποτελέσματα.
    https://doc.qt.io/qt-5/qobject.html#...nment-operator

    Στις αντίστοιχες περιπτώσεις τότε είτε και εσύ τον κάνεις Private και δεν την καλείς ποτέ (με new όπως είπες για το compile), είτε φτιάχνεις όλη τη λογική ώστε να κάνεις new και να φέρεις όλο το αντικείμενο στην αντίστοιχη κατάσταση (με μεθόδους - αναθέσεις κτλ).

  3. #3
    Εγγραφή
    14-02-2003
    Περιοχή
    Θεσσαλονίκη
    Μηνύματα
    1.215
    Downloads
    19
    Uploads
    0
    ISP
    -
    Το βασικό θέμα είναι:
    Γιατι η parent class εχει deleted copy constructor;
    Μήπως γιατί δεν είναι τεχνικώς εφικτό να αντιγραφεί;
    Οπότε σε αυτήν την περίπτωση, πως στην παραγόμενη κλάση θα πετύχεις το initialization;
    Χωρίς να το ψάξω ιδιαίτερα, νομίζω πως ό,τι και να κάνεις, θεωρώ ότι θα μείνεις με ένα "μισό" αντικείμενο στό τέλος.
    Εκτιμώ ότι δεν είναι δυνατό να αντιγραφεί και θα συμβούλευα να κανεις delete copy constructor/operator=

  4. #4
    Εγγραφή
    04-02-2009
    Ηλικία
    33
    Μηνύματα
    1.486
    Downloads
    4
    Uploads
    0
    Τύπος
    ADSL
    Ταχύτητα
    2048/256
    ISP
    Cyta Hellas
    Ευχαριστώ για τις απαντήσεις σας παιδιά.

    Το βασικό πρόβλημα είναι ότι αν τους δηλώσω default / delete τότε υπάρχει πρόβλημα στο compiling με την macro Q_DECLARE_METATYPE( PushButton ).
    Αλλά έστω και έτσι αν υποθέσουμε ότι δεν χρειάζεται η macro και πως δεν είναι deleted ο copy ctor της προηγούμενης κλάσης. Όλα τα παραδείγματα μιλάνε για private member στα οποία καταχωρούνται οι νέες τιμές. Αν δεν έχω κάτι να αρχικοποιήσω, τότε ποια είναι η τύχη του this;

    Πρέπει να πάρει κάπως την διεύθυνση του other; Από ό,τι μου είπαν ποτέ μα ποτέ δε κάνουμε assignement απευθείας στο this pointer. Και βέβαια γίνεται να τον κάνεις default ή deleted αλλά για εκπαιδευτικούς λόγους ψάχνω να μάθω έστω πως το λύνει ο compiler.
    Με ΜΑΤ και βία δεν βγαίνει πανδημία, Μιχαλάκη και Κούλη.

  5. #5
    Εγγραφή
    13-11-2011
    Περιοχή
    Χολαργός
    Ηλικία
    37
    Μηνύματα
    1.438
    Downloads
    1
    Uploads
    0
    Τύπος
    VDSL2
    Ταχύτητα
    24000 / 4500
    ISP
    Wind
    DSLAM
    Wind - ΧΟΛΑΡΓΟΣ
    Path Level
    Interleaved
    Το "this" δεν αλλάζει επειδή κλήθηκε ο copy constructor. Δείχνει πάντα το αντικείμενο στο οποίο βρίσκεσαι, άρα δεν έχει κάτι να κάνει με την "τύχη" του, πάντα το ίδιο αντικείμενο δείχνει. Αν πάρει την διεύθυνση του Other τότε είναι ένας απλός Pointer σε ένα αντικείμενο και όχι ένα καινούργιο αντικείμενο.

    Ο copy constructor καλείται στο καινούριο αντικείμενο, όχι στο παλιό! Είναι ένας ακόμη constructor που σαν όρισμα παίρνει ένα άλλο αντικείμενο ίδιου τύπου, δεν διαφέρει σε τίποτα από τον απλό constructor, απλά τον ονομάζουμε copy!

    Το νόημα του copy constructor είναι αρκετά απλό, θέλεις να αντιγράψεις ένα αντικείμενο και να το έχεις δύο φορές στη μνήμη. Αν αφήσεις απλά τον compiler να το κάνει τότε μεταφέρει όλες τις primitive μεταβλητές. Αυτό δεν είναι από μόνο του κακό. Το πρόβλημα έρχεται όταν έχεις δυναμικές τιμές μέσα στο αντικείμενο (πχ έναν pointer που το έχεις κάνει πίνακα). Τότε αντιγράφεται η primitive μεταβλητή, που είναι ο pointer. Άρα και τα δύο αντικείμενα δείχνουν στον ίδιο πίνακα και δεν είναι πλέον αντίγραφα το ένα του άλλου. Αυτό το πρόβλημα λύνει ο copy constructor, μπορείς να φτιάξεις ένα καινούργιο αντικείμενο και να του περάσεις σαν όρισμα ένα άλλο που θέλεις να αντιγράψεις. Αν πχ ο πίνακας ήταν public τότε ο copy constructor θα αντέγραφε τον public πίνακα, για να μην χρειάζεται να το κάνει ο χρήστης. Αν ήταν private όμως ο χρήστης δεν μπορεί να το κάνει καν, οπότε επειδή ο constructor είναι στην ίδια κλάση, έχει πρόσβαση και και στις private μεταβλητές, οπότε μπορεί να "δουλέψει" και με αυτές.

  6. #6
    Εγγραφή
    04-02-2009
    Ηλικία
    33
    Μηνύματα
    1.486
    Downloads
    4
    Uploads
    0
    Τύπος
    ADSL
    Ταχύτητα
    2048/256
    ISP
    Cyta Hellas
    Παράθεση Αρχικό μήνυμα από MitsakosGR Εμφάνιση μηνυμάτων
    Το "this" δεν αλλάζει επειδή κλήθηκε ο copy constructor. Δείχνει πάντα το αντικείμενο στο οποίο βρίσκεσαι, άρα δεν έχει κάτι να κάνει με την "τύχη" του, πάντα το ίδιο αντικείμενο δείχνει. Αν πάρει την διεύθυνση του Other τότε είναι ένας απλός Pointer σε ένα αντικείμενο και όχι ένα καινούργιο αντικείμενο.

    Ο copy constructor καλείται στο καινούριο αντικείμενο, όχι στο παλιό! Είναι ένας ακόμη constructor που σαν όρισμα παίρνει ένα άλλο αντικείμενο ίδιου τύπου, δεν διαφέρει σε τίποτα από τον απλό constructor, απλά τον ονομάζουμε copy!

    Το νόημα του copy constructor είναι αρκετά απλό, θέλεις να αντιγράψεις ένα αντικείμενο και να το έχεις δύο φορές στη μνήμη. Αν αφήσεις απλά τον compiler να το κάνει τότε μεταφέρει όλες τις primitive μεταβλητές. Αυτό δεν είναι από μόνο του κακό. Το πρόβλημα έρχεται όταν έχεις δυναμικές τιμές μέσα στο αντικείμενο (πχ έναν pointer που το έχεις κάνει πίνακα). Τότε αντιγράφεται η primitive μεταβλητή, που είναι ο pointer. Άρα και τα δύο αντικείμενα δείχνουν στον ίδιο πίνακα και δεν είναι πλέον αντίγραφα το ένα του άλλου. Αυτό το πρόβλημα λύνει ο copy constructor, μπορείς να φτιάξεις ένα καινούργιο αντικείμενο και να του περάσεις σαν όρισμα ένα άλλο που θέλεις να αντιγράψεις. Αν πχ ο πίνακας ήταν public τότε ο copy constructor θα αντέγραφε τον public πίνακα, για να μην χρειάζεται να το κάνει ο χρήστης. Αν ήταν private όμως ο χρήστης δεν μπορεί να το κάνει καν, οπότε επειδή ο constructor είναι στην ίδια κλάση, έχει πρόσβαση και και στις private μεταβλητές, οπότε μπορεί να "δουλέψει" και με αυτές.
    To bold έχει να κάνει με το λεγόμενο deep και shallow copy ή τα έχω καταμπερδέψει;

    Όπως και να χει πολύ επεξηγηματική η απάντησή σου, ευχαριστώ.
    Με ΜΑΤ και βία δεν βγαίνει πανδημία, Μιχαλάκη και Κούλη.

  7. #7
    Εγγραφή
    19-06-2008
    Περιοχή
    127.0.0.1
    Μηνύματα
    1.147
    Downloads
    0
    Uploads
    0
    Τύπος
    ADSL2+
    Ταχύτητα
    14000/700
    ISP
    Conn-x OTE
    Router
    cisco887va+sec-k9
    Path Level
    Fastpath
    Το QPushButton εχει ετοιμο copy constructor? Αν ναι, θα κλειθει μονος του. Εσυ ασχολείσαι μονο με τα δικα σου data.
    Μπορεις να τον καλεσεις και explicitly.

    Δεν θα ηταν consistent να πρεπει ενα derived class να ασχολειτσι με στοιχεια του base class. Αυτο δεν θα ηταν obj oriented programming
    Τελευταία επεξεργασία από το μέλος bxenos : 30-12-20 στις 05:38.

  8. #8
    Εγγραφή
    13-11-2011
    Περιοχή
    Χολαργός
    Ηλικία
    37
    Μηνύματα
    1.438
    Downloads
    1
    Uploads
    0
    Τύπος
    VDSL2
    Ταχύτητα
    24000 / 4500
    ISP
    Wind
    DSLAM
    Wind - ΧΟΛΑΡΓΟΣ
    Path Level
    Interleaved
    Παράθεση Αρχικό μήνυμα από petran_18 Εμφάνιση μηνυμάτων
    To bold έχει να κάνει με το λεγόμενο deep και shallow copy ή τα έχω καταμπερδέψει;

    Όπως και να χει πολύ επεξηγηματική η απάντησή σου, ευχαριστώ.
    Ακριβώς!
    Shallow copy ονομάζουμε όταν μεταφέρεις μόνο primitive τιμές (αυτό που κάνει ο default copy constructor). Ότι βρίσκει το αντιγράφει όπως ακριβώς είναι! Επειδή πολλές μεταβλητές είναι δείκτες, αντιγράφει τον δείκτη, όχι το αντικείμενο στο οποίο δείχνει ο δείκτης.
    Deep copy είναι να βάλεις και λογική από πίσω ώστε να μην αντιγράψεις το reference (pointer) αλλά να πας πιο βαθιά και να αντιγράψεις το αντικείμενο που δείχνει ο pointer.

    Παράθεση Αρχικό μήνυμα από bxenos Εμφάνιση μηνυμάτων
    Το QPushButton εχει ετοιμο copy constructor? Αν ναι, θα κλειθει μονος του. Εσυ ασχολείσαι μονο με τα δικα σου data.
    Μπορεις να τον καλεσεις και explicitly.

    Δεν θα ηταν consistent να πρεπει ενα derived class να ασχολειτσι με στοιχεια του base class. Αυτο δεν θα ηταν obj oriented programming
    Η QPushButton έχει private copy constructor ακριβώς για να μην αντιγράφεται, οπότε οποιαδήποτε προσπάθεια κλήσης του copy constructor βγάζει compile error.

  9. #9
    Εγγραφή
    04-02-2009
    Ηλικία
    33
    Μηνύματα
    1.486
    Downloads
    4
    Uploads
    0
    Τύπος
    ADSL
    Ταχύτητα
    2048/256
    ISP
    Cyta Hellas
    Πολύ ωραία, σας ευχαριστώ όλους για την διαφωτιστική κουβέντα!
    Με ΜΑΤ και βία δεν βγαίνει πανδημία, Μιχαλάκη και Κούλη.

Bookmarks

Bookmarks

Δικαιώματα - Επιλογές

  • Δεν μπορείτε να δημοσιεύσετε νέα θέματα
  • Δεν μπορείτε να δημοσιεύσετε νέα μηνύματα
  • Δεν μπορείτε να αναρτήσετε συνημμένα
  • Δεν μπορείτε να επεξεργαστείτε τα μηνύματα σας
  •  
  • Τα BB code είναι σε λειτουργία
  • Τα Smilies είναι σε λειτουργία
  • Το [IMG] είναι σε λειτουργία
  • Το [VIDEO] είναι σε λειτουργία
  • Το HTML είναι εκτός λειτουργίας