User Tools

Site Tools


cpp:class_templates_specialization

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Next revision Both sides next revision
cpp:class_templates_specialization [2019/05/14 04:23]
gthanos
cpp:class_templates_specialization [2021/06/04 17:44]
gthanos
Line 1: Line 1:
 ====== Εξειδίκευση ενός υφιστάμενου template ====== ====== Εξειδίκευση ενός υφιστάμενου template ======
 +
 +===== Εξειδίκευση της κλάσης Box στην περίπτωση που η παράμετρος είναι δείκτης =====
  
 Συχνά είναι απαραίτητο να προδιαγράψουμε διαφορετική λειτουργικότητα σε ένα template με βάση τον τύπο των δεδομένων που θα εισαχθεί τελικά στην κλάση. Για παράδειγμα, για την κλάση **Box<T>** που είδαμε προηγουμένως, οφείλουμε να εισάγουμε διαφορετική λειτουργικότητα όταν ο τύπος δεδομένων είναι δείκτης αντί για κανονική μεταβλητή. Ο λόγος είναι ότι σε αυτή την περίπτωση δεν αρκεί η απλή αντιγραφεί του δείκτη, αλλά θα πρέπει να δεσμευθεί ο απαραίτητος χώρος στη μνήμη προκειμένου η κλάση να δημιουργήσει ένα αντίγραφο της υφιστάμενης πληροφορίας που περνιέται μέσω του δείκτη. Το παράδειγμα εξειδίκευσης της κλάσης **Box<T>** όταν περνιέται δείκτης δίνεται παρακάτω: Συχνά είναι απαραίτητο να προδιαγράψουμε διαφορετική λειτουργικότητα σε ένα template με βάση τον τύπο των δεδομένων που θα εισαχθεί τελικά στην κλάση. Για παράδειγμα, για την κλάση **Box<T>** που είδαμε προηγουμένως, οφείλουμε να εισάγουμε διαφορετική λειτουργικότητα όταν ο τύπος δεδομένων είναι δείκτης αντί για κανονική μεταβλητή. Ο λόγος είναι ότι σε αυτή την περίπτωση δεν αρκεί η απλή αντιγραφεί του δείκτη, αλλά θα πρέπει να δεσμευθεί ο απαραίτητος χώρος στη μνήμη προκειμένου η κλάση να δημιουργήσει ένα αντίγραφο της υφιστάμενης πληροφορίας που περνιέται μέσω του δείκτη. Το παράδειγμα εξειδίκευσης της κλάσης **Box<T>** όταν περνιέται δείκτης δίνεται παρακάτω:
  
-<code cpp BoxTPtr.hpp>+<code cpp BoxPtr.hpp>
 #ifndef _BOXTPTR_HPP_ #ifndef _BOXTPTR_HPP_
 #define _BOXTPTR_HPP_ #define _BOXTPTR_HPP_
Line 74: Line 76:
 #endif #endif
 </code> </code>
 +
 +Παρακάτω παρατίθεται κώδικας ο οποίος χρησιμοποιεί την παραπάνω εξειδίκευση του //template//
 +
 +<code cpp BoxPtrUsage.cpp>
 +#include <iostream>
 +#include "BoxPtr.hpp"
 +#include "Student.hpp"
 +
 +using namespace std;
 +
 +int main() {
 +  int a=5;
 +  double d(4.23);
 +  Student kate = {"Kate", 1234};
 +  
 +  Box<int*> intBox(&a);
 +  Box<double*> doubleBox(&d);
 +  Box<Student*> studentBox(&kate);
 +  Student* kate_ptr = studentBox.get();
 +    
 +  cout << *kate_ptr << endl;
 +  delete kate_ptr;
 +  kate.setName("Katerina");
 +  cout << kate << endl;
 +}
 +</code>
 +
 +<WRAP todo 80% center round>
 +Στον παραπάνω κώδικα αντικαταστήστε την  εντολή ''#include "BoxPtr.hpp"'' με την εντολή ''#include "Box.hpp"'' και παρατηρήστε την αλλαγή στη συμπεριφορά του προγράμματος. To πρόγραμμα θα τερματίσει τη λειτουργία του (Γιατί?) με ένα μήνυμα της μορφής:
 +<code>
 +*** Error in `./BoxPtrUsage': double free or corruption (out): 0x00007ffc4f49ed10 ***
 +======= Backtrace: =========
 +/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f40da1757e5]
 +/lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7f40da17e37a]
 +/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f40da18253c]
 +</code>
 +</WRAP>
 +
 +===== Εξειδίκευση της κλάσης Box στην περίπτωση που η παράμετρος είναι δείκτης σε χαρακτήρα =====
  
 Το παραπάνω παράδειγμα είναι ικανοποιητικό εάν περαστεί ως δείκτης ένα αντικείμενο τύπου **int* ** ή **Student* **, όμως δεν είναι ικανοποιητικό εάν περαστεί ένας δείκτης τύπου **char* ** που αντιπροσωπεύει ένα C string. Σε αυτή την περίπτωση δεν αρκεί να δεσμευθεί η μνήμη για ένα χαρακτήρα, αλλά θα πρέπει α) να αναγνωρίσουμε το μέγεθος της συμβολοσειράς που πρέπει να αντιγραφεί και β)πριν γίνει η αντιγραφή της συμβολοσειράς να δεσμευθεί ο απαραίτητος χώρος για αυτή. Το παραπάνω παράδειγμα είναι ικανοποιητικό εάν περαστεί ως δείκτης ένα αντικείμενο τύπου **int* ** ή **Student* **, όμως δεν είναι ικανοποιητικό εάν περαστεί ένας δείκτης τύπου **char* ** που αντιπροσωπεύει ένα C string. Σε αυτή την περίπτωση δεν αρκεί να δεσμευθεί η μνήμη για ένα χαρακτήρα, αλλά θα πρέπει α) να αναγνωρίσουμε το μέγεθος της συμβολοσειράς που πρέπει να αντιγραφεί και β)πριν γίνει η αντιγραφή της συμβολοσειράς να δεσμευθεί ο απαραίτητος χώρος για αυτή.
Line 136: Line 177:
 #endif #endif
 </code> </code>
 +
 +Παράδειγμα κώδικα που χρησιμοποιεί την παραπάνω εξειδικευμένη κλάση **Box<char*>** δίνεται παρακάτω:
 +<code cpp BoxCharPtrUsage.cpp>
 +#include <iostream>
 +#include "Box.hpp"
 +#include "Student.hpp"
 +
 +using namespace std;
 +
 +int main() {
 +  char greeting[64] = "Wellcome C++ in CE325 course";
 +  
 +  Box<char*> greetingBox(greeting);
 +  
 +  char* greeting_copy = greetingBox.get();
 +  cout << greeting_copy << endl;
 +  delete greeting_copy;
 +  
 +  Box<char*> msgBox = greetingBox;
 +  char* msg = msgBox.get();
 +  cout << msg << endl;
 +  delete msg; 
 +}
 +</code>
 +
 +<WRAP todo 80% center round>
 +Στον παραπάνω κώδικα αντικαταστήστε την εντολή ''#include "BoxCharPtr.hpp"'' με την εντολή ''#include "BoxPtr.hpp"'' και στη συνέχεια με την εντολή ''#include "Box.hpp"''. Παρατηρήστε την αλλαγή στη συμπεριφορά του προγράμματος. Σε τι οφείλεται αυτό;
 +</WRAP>
cpp/class_templates_specialization.txt · Last modified: 2022/05/26 10:47 by gthanos