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

Next revision
Previous revision
cpp:class_templates_specialization [2019/05/14 04:15] – created gthanoscpp:class_templates_specialization [2022/05/26 10:47] (current) – [Εξειδίκευση της κλάσης Box στην περίπτωση που η παράμετρος είναι δείκτης σε χαρακτήρα] gthanos
Line 1: Line 1:
-====== Εξειδίκευση ενός template ======+====== Εξειδίκευση ενός υφιστάμενου template ======
  
-Συχνά είναι απαραίτητο να προδιαγράψουμε διαφορετική λειτουργικότητα σε ένα template με βάση τον τύπο των δεδομένων που θα εισαχθεί τελικά στην κλάση. Για παράδειγμα, για την κλάση **Box<T>** πρέπει να εισάγουμε διαφορετική λειτουργικότητα εάν ο τύπος δεδομένων είναι δείκτης, διότι σε αυτή την περίπτωση δεν αρκεί η απλή αντιγραφεί του δείκτη, αλλά θα πρέπει να δεσμευθεί ο απαραίτητος χώρος στη μνήμη προκειμένου η κλάση να δημιουργήσει ένα αντίγραφο της υφιστάμενης πληροφορίας που περνιέται μέσω του δείκτη. Το παράδειγμα εξειδίκευσης της κλάσης **Box<T>** όταν περνιέται δείκτης δίνεται παρακάτω:+===== Εξειδίκευση της κλάσης Box στην περίπτωση που η παράμετρος είναι δείκτης ===== 
 + 
 +Συχνά είναι απαραίτητο να προδιαγράψουμε διαφορετική λειτουργικότητα σε ένα template με βάση τον τύπο των δεδομένων που θα εισαχθεί τελικά στην κλάση. Για παράδειγμα, για την κλάση **Box<T>** που είδαμε προηγουμένως, οφείλουμε να εισάγουμε διαφορετική λειτουργικότητα όταν ο τύπος δεδομένων είναι δείκτης αντί για κανονική μεταβλητή. Ο λόγος είναι ότι σε αυτή την περίπτωση δεν αρκεί η απλή αντιγραφεί του δείκτη, αλλά θα πρέπει να δεσμευθεί ο απαραίτητος χώρος στη μνήμη προκειμένου η κλάση να δημιουργήσει ένα αντίγραφο της υφιστάμενης πληροφορίας που περνιέται μέσω του δείκτη. Το παράδειγμα εξειδίκευσης της κλάσης **Box<T>** όταν περνιέται δείκτης δίνεται παρακάτω: 
 + 
 +<code cpp BoxPtr.hpp> 
 +#ifndef _BOXTPTR_HPP_ 
 +#define _BOXTPTR_HPP_
  
-<code cpp BoxTemplateSpecialization1.hpp> 
 #include "Box.hpp" #include "Box.hpp"
 +
 template<typename T> template<typename T>
 class Box<T*> { class Box<T*> {
Line 70: Line 76:
   return *this;   return *this;
 } }
 +#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. Σε αυτή την περίπτωση δεν αρκεί να δεσμευθεί η μνήμη για ένα χαρακτήρα, αλλά θα πρέπει α) να αναγνωρίσουμε το μέγεθος της συμβολοσειράς που πρέπει να αντιγραφεί και β)πριν γίνει η αντιγραφή της συμβολοσειράς να δεσμευθεί ο απαραίτητος χώρος για αυτή.
 +
 +<code cpp BoxCharPtr.hpp>
 +#ifndef _BOXCHARPTR_HPP_
 +#define _BOXCHARPTR_HPP_
 +
 +#include "Box.hpp"
 +#include <cstring>
 +
 +template <>
 +class Box<char *> {
 +  char *e;
 +public:
 +  Box();
 +  Box(char *e);
 +  ~Box();
 +  Box(const Box<char*>& b);
 +  char* get() const;
 +  void set(char *e);
 +  Box<char*>& operator=(Box<char*>& b);
 +  friend std::ostream& operator<<(std::ostream& out, const Box<char*>& t);
 +};
 +
 +Box<char*>::Box() {
 +  this->e = nullptr;
 +}
 +
 +Box<char*>::Box(char *e) {
 +  this->e = new char[strlen(e)+1];
 +  strcpy(this->e, e);
 +}
 +
 +Box<char*>::Box(const Box<char*>& b) {
 +  this->e = new char[strlen(b.e)+1];
 +  strcpy(this->e, b.e);
 +}
 +
 +Box<char*>::~Box() {
 +  delete [] this->e;
 +}
 +
 +char* Box<char*>::get() const { 
 +  char *ce = new char[strlen(e)+1];
 +  strcpy(ce, e);
 +  return ce;
 +}
 +
 +void Box<char *>::set(char *e) {
 +  if(this->e!=nullptr)
 +    delete [] this->e;
 +  this->e = new char[strlen(e)+1];
 +  strcpy(this->e, e);
 +}
 +
 +Box<char*>& Box<char*>::operator=(Box<char*>& b){
 +  set(b.e);
 +  return *this;
 +}
 +
 +std::ostream& operator<<(std::ostream& out, const Box<char*>& t) {
 +  out << t.e;
 +  return out;
 +}
 +#endif
 +</code>
 +
 +Παράδειγμα κώδικα που χρησιμοποιεί την παραπάνω εξειδικευμένη κλάση **Box<char*>** δίνεται παρακάτω:
 +<code cpp BoxCharPtrUsage.cpp>
 +#include <iostream>
 +
 +#include "BoxCharPtr.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.1557807309.txt.gz · Last modified: 2019/05/14 03:15 (external edit)