tr3quart1sta Δημοσ. 19 Οκτωβρίου 2013 Δημοσ. 19 Οκτωβρίου 2013 Έχω μια class MyString: MyString.h #include <tr1/memory> #include <iostream> #include <string> #include <cstring> using namespace std; class MyString final { // private Datenstruktur char* m_string[]; size_t m_len; shared_ptr<char> m_start; public: // öffentliche Methoden MyString(); MyString(const MyString& ms); MyString(const char* cstr); ~MyString(); // Instanz-Methoden . . . } MyString.cpp #include "MyString.h" #include <tr1/memory> #include <iostream> #include <string> #include <cstring> using namespace std; MyString::MyString() : m_len(0) , m_start(nullptr) { cout << "def. constr." << endl; } MyString::MyString(const MyString& ms) : m_len(ms.m_len) { cout << "copy constr" << endl;} MyString::MyString(const char* cstr) // TYPE CONVERTER CONSTRUCTOR { size_t a = 0; while (cstr[a] != '\0'){ a++; } m_len = a; auto temp = unique_ptr<char[]>(new char[m_len]); for(size_t i = 0; i < m_len; i++){ temp[i] = cstr[i]; } m_string = temp; cout << "typkonv. constr." << ", size: " << m_len << endl; } MyString::~MyString() { delete[] m_string; } char MyString::charAt(size_t index) const{ return *m_string[index]; } και το προβλημα ειναι οτι στον type converter constructor πρεπει το m_string να ειναι τυπου shared_ptr (ναι, μπορω να του περασω και unique_ptr), ενω στο .h ειναι δηλωμενο ως char* [] και υπαρχει ασυμβατοτητα τυπων. Πως μπορω να το περασω αυτο?
παπι Δημοσ. 19 Οκτωβρίου 2013 Δημοσ. 19 Οκτωβρίου 2013 (επεξεργασμένο) Τα εχεις ψιλομπερδεψει. 1) Δεν υπαρχει type conversion constructor 2) το shared_ptr ειναι smart pointer. Δες λιγο στο google ποια ειναι η δουλεια του. Αν θες να βοηθησω, γραψε λιγο ποια συμπεριφορα θελεις απο αυτο το object. edit: Μαλλον εγω τα εχω μπερδεψει.... Υπαρχει conversion constructor, απλα το εχω στο μυαλο μου με αλλη ορολογια (implicit/explicit constructor) Επεξ/σία 20 Οκτωβρίου 2013 από παπι
tr3quart1sta Δημοσ. 19 Οκτωβρίου 2013 Μέλος Δημοσ. 19 Οκτωβρίου 2013 Αυτος ο constructor πρεπει να δεχεται ενα C-String, τυπου const char* και να δημιουργει ενα deep copy. Το σημαντικο κομματι αυτου του constructor ειναι η σωστη δημιουργια του pointer: shared_ptr<char> m_string. Αυτος ο pointer δειχνει μονο στο πρωτο char και οχι σε ολοκληρο το array το οποιο θα φερει προβληματα κατα την διαγραφη του. Σε αντιθεση με το shared_ptr<>, μπορει το unique_ptr<> να δουλεψει σωστα με C-Arrays. Η εντολη unique_ptr<char[]>(new char[m_len]) δημιουργει ενα Character-Array πανω στον Heap και ο pointer καθιστα σιγουρο το οτι αργοτερα θα διαγραφει ολοκληρο το array. Το attribute m_string θα πρεπει να ειναι ομως τυπου shared_ptr<char> το οποιο δεν ειναι προβλημα καθως ο constructor του shared_ptr<char> μπορει να παρει και ως παραμετρο εναν unique_ptr<char[]>.
παπι Δημοσ. 19 Οκτωβρίου 2013 Δημοσ. 19 Οκτωβρίου 2013 Καμια σχεση. Και τα δυο (shared,unique) ειναι smart pointers. Η διαφορα τους ειναι οτι ο unique δεν μπορει να γινει copy. Και οι δυο θα δουλεψουν λαθος στην περιπτωση σου, επειδη και οι δυο καλουν delete και οχι delete[]. Για να δουλεψουν σωστα, θες deleter px (βλεπω οτι παιζεις με c++0x, θα βαλω labda ) #include <iostream> #include <functional> #include <memory> struct Foo { Foo() { std::cout<<"Foo created!"<<std::endl; } ~Foo() { std::cout<<"Foo deleted!"<<std::endl; } }; int main() { { std::shared_ptr<Foo> farr(new Foo[3],[](Foo* p){delete[] p;}); //ok } { std::shared_ptr<Foo> farr(new Foo[3]); //kai crash } return 0; } Επειδη εισαι στο μαθαινω, μη μπλεξεις με smart pointer (βεβαια ριξε ενα διαβασμα να δεις πως παιζουν), παιξε με τις λειτουργιες τς class. Δηλαδη, υλοποιησε τα παρακατω constructor destructor copy constructor assignment operator και εφοσον εισαι σε c++0x δες και τους move constructor move assignment operator
tr3quart1sta Δημοσ. 19 Οκτωβρίου 2013 Μέλος Δημοσ. 19 Οκτωβρίου 2013 ναι αυτο που λες μας το εχουν σαν εναλλακτικη, αλλα γραφουνε να χρησιμοποιησοθμε την εντολη με το unique οπως εγραψα πιο πανω.. αλλα ακομα δεν εχω καταλαβει πως θα αποθηκευσω το m_string σε αυτον τον constructor
παπι Δημοσ. 19 Οκτωβρίου 2013 Δημοσ. 19 Οκτωβρίου 2013 (επεξεργασμένο) Τι πανε και σας βαζουν... Θα το περασεις ετσι template<class T> struct deleter { void operator()(T *p) { delete[] p; } }; class String { std::unique_ptr<char,deleter<char> > ptr; size_t size; public: String() : ptr(nullptr),size(0) { } String(const char* str) { size = strlen(str); ptr = std::unique_ptr<char,deleter<char> > (new char[size+1]); strcpy(ptr.get(),str); } }; υγ ΔΕΝ κανεις delete αυτο που εβαλες μεσα στο smart pointer! ΔΕΝ κανεις copy τον αυτον τον smart ptr. (δες για move constructors) btw, εισαι σε ξενω ΑΕΙ; Μου κανει μεγαλη εντυπωση αυτα που σας μαθαινουν. Επεξ/σία 20 Οκτωβρίου 2013 από παπι
παπι Δημοσ. 20 Οκτωβρίου 2013 Δημοσ. 20 Οκτωβρίου 2013 template<class T> struct deleter { void operator()(T *p) { delete[] p; } }; class String { /* Αυτος ο smart pointer δεν αφηνει να υπαρχουν πανω απο ενα reference ουσιαστικα δεν εχει copy πχ δεν μπορεις να κανεις κατι τετοιο unique_ptr<..> p1 = p; η δουλεια του στη κλαση ειναι να κανει 'tracking' το reference δηλαδη να μην χρειαζεται να καλεσουμε το πρωτογονο delete επειδη το reference δεν ειναι κατι το standar, πρεπει να ορισεις και εναν deleter (o default ειναι το delete) */ std::unique_ptr<char,deleter<char> > ptr; size_t size; public: String() : ptr(nullptr),size(0) { } String(const char* str) { size = strlen(str); /* η δουλεια του smart pointer ειναι να managaρει ενα reference, αρα ειναι λαθος να εχεις το ιδιο reference εκτος του smart ptr Ετσι, οτι παιρνεις απο την new, το βαζεις αμεσως μεσα στο smart pointer. Και οταν θες αυτο το reference, τοτε το παιρνεις απο το smart pointer. -------->>>> ΔΕΝ ΧΡΕΙΑΖΕΣΑΙ ΤΟ m_string που εχεις! διεγραψε το, και αλλαξε το ονομα του smart pointer σε m_string για να μην μπερδευεσαι (υπαρχουν πολλα operators overload στο smart pointer που το κανουν να συμπεριφερεται σα pointer) */ ptr = std::unique_ptr<char,deleter<char> > (new char[size+1]); strcpy(ptr.get(),str); } String(const String& str) : size(str.size) { /* Το deep copy ειναι ουσιαστικα η αντιγραφη των δεδομενων που εχουν τα reference ενος object αρα κανουμε το ιδιο πραγμα που κανουμε και στο String(const char*) */ ptr = std::unique_ptr<char,deleter<char> > (new char[size+1]); strcpy(ptr.get(),str.ptr.get()); } };
tr3quart1sta Δημοσ. 21 Οκτωβρίου 2013 Μέλος Δημοσ. 21 Οκτωβρίου 2013 update: MyString.h #ifndef MYSTRING_H_ #define MYSTRING_H_ #include <tr1/memory> #include <iostream> #include <string> #include <cstring> using namespace std; class MyString final { // private Datenstruktur size_t m_len; shared_ptr<char> m_string; size_t m_start; public: // öffentliche Methoden MyString(); MyString(const MyString& other); MyString(const char* other); ~MyString(); // Instanz-Methoden char charAt(size_t index) const; // bei falschem Index: wirft exception }; #endif /* MYSTRING_H_ */ MyString.cpp #include "MyString.h" #include <tr1/memory> #include <iostream> #include <string> #include <cstring> MyString::MyString() : m_len(0) , m_string(nullptr) , m_start(0) { cout << "default constr." << endl;} MyString::MyString(const MyString& other) : m_len(other.m_len) , m_string(other.m_string) , m_start(other.m_start) { /*m_string = unique_ptr<char> (new char[m_len +1]); strcpy(m_string.get(), other.m_string.get());*/ cout << "copy constr." << endl; } MyString::MyString(const char* other) : m_start(0) { m_len = strlen(other); m_string = unique_ptr<char> (new char[m_len +1]); strcpy(m_string.get(), other); cout << "typkonv. constr." << endl; } MyString::~MyString() { cout << "deconstr." << endl;} char MyString::charAt(size_t index) const { auto p = m_string.get(); return p[index]; } main.cpp #include "MyString.h" #include <iostream> #include <tr1/memory> #include <string> #include <cstring> using namespace std; int main() { MyString a; MyString b(a); MyString c("abcdef"); size_t index = 0; cout << "c.charAT(" << index << "): " << c.charAt(index) << endl; cout << "Hello World!" << endl; // prints Hello World! return 0; } run> default constr. copy constr. typkonv. constr. c.charAT(0): a Hello World! deconstr. deconstr. deconstr.
tr3quart1sta Δημοσ. 27 Οκτωβρίου 2013 Μέλος Δημοσ. 27 Οκτωβρίου 2013 για να μην μπορει να αλλαξει τιμες ενα αντικειμενο του class MyString (δλδ initialize και τελος) πρεπει ο "operator=" να πεταει exception ή πως γινεται?? MyString.cpp #include "MyString.h" #include <tr1/memory> #include <iostream> #include <string> #include <cstring> #include <exception> using namespace std; MyString::MyString() : m_len(0) , m_string(nullptr) , m_start(0) { cout << "default constr." << endl; this->myprint(); } MyString::MyString(const MyString& other) : m_len(other.m_len) , m_string(other.m_string) , m_start(other.m_start) { cout << "copy constr." << endl; this->myprint(); } MyString::MyString(MyString&& other) : m_len(other.m_len) , m_string(other.m_string) , m_start(other.m_start) { other.m_len = 0; other.m_string = nullptr; other.m_start = 0; cout << "move copy constr." << endl; /*cout << "this: " << endl; this->myprint(); cout << "other: " << endl; other.myprint();*/ } MyString::MyString(const char* other) : m_start(0) { m_len = slen(other); m_string = shared_ptr<char>(unique_ptr<char[]>(new char[m_len])); memcpy(m_string.get(), other, m_len +1); cout << "typkonv. constr." << endl; this->myprint(); } MyString MyString::operator=(const MyString& other){ // <======= //exception ?? return NULL; } /*MyString MyString::operator=(const MyString&& other){ // <======= //exception ?? return NULL; }*/ MyString::~MyString() { cout << "deconstr." << endl << endl; } char MyString::charAt(size_t index) const { auto p = m_string.get(); return p[index]; } int MyString::compareTo(const MyString& other) const { if(m_len > other.m_len){ return 1; }else if(m_len < other.m_len){ return -1; }else{ return 0; } } size_t MyString::getLen() const{ return m_len; } MyString MyString::concat(char c) const{ auto my = m_string.get(); auto f = new char[m_len+1]; for(size_t i = 0; i< m_len; i++){ f[i] = my[i]; } f[m_len] = c; f[m_len+1] = '\0'; auto p = MyString(f); return move(p); } MyString MyString::concat(const MyString& other) const{ auto o = other.m_string.get(); auto my = m_string.get(); size_t newsize = m_len + other.m_len +1; auto k = new char[newsize]; for(size_t i= 0; i< m_len; i++){ k[i] = my[i]; } for(size_t j= 0; j< m_len; j++){ k[j + m_len] = o[j]; } k[m_len + other.m_len] = '\0'; auto p = MyString(k); return move(p); } MyString MyString::substring(size_t beg, size_t end) const{ if(beg<m_len && end<m_len && beg < end){ auto my = m_string.get(); auto f = new char[(end-beg)+1]; for(size_t i = beg; i< end; i++){ f[i-beg] = my[i]; } f[end] = '\0'; auto p = MyString(f); return p; }else { auto k = ""; auto y = MyString(k); return y; } } unique_ptr<char[]> MyString::toCString() const{ auto my = m_string.get(); if(m_len == 0){ auto k = new char[1]; k[0] = '\0'; auto u1 = unique_ptr<char[]>(k); return u1; }else { auto f = new char[m_len+1]; for(size_t i = 0; i< m_len; i++){ f[i] = my[i]; } auto u2 = unique_ptr<char[]>(f); return u2; } } void MyString::myprint() const{ auto my = m_string.get(); if(m_len == 0){ cout << "zerolen" << endl; }else { for(size_t i = 0; i<m_len+1; i++){ if(my[i] == '\0'){ cout << "print(): charAt(" << i << "): " << "zero" << endl; }else{ cout << "print(): charAt(" << i << "): " << my[i] << endl; } } } cout << endl; } MyString MyString::valueOf(int i){ auto k = new char[2]; k[0] = (char) i; k[1] = '\0'; auto p = MyString(k); return p; } size_t MyString::slen(const char* other) const{ size_t l = 0; while(other[l] != '\0'){ l++; } return l; } MyString.h #ifndef MYSTRING_H_ #define MYSTRING_H_ #include <tr1/memory> #include <iostream> #include <string> #include <cstring> #include <exception> using namespace std; class MyString final { // private Datenstruktur size_t m_len; shared_ptr<char> m_string; size_t m_start; public: // öffentliche Methoden MyString(); MyString(const MyString& other); MyString(MyString&& other); MyString(const char* other); MyString operator=(const MyString&); ~MyString(); // Instanz-Methoden char charAt(size_t index) const; // bei falschem Index: wirft exception int compareTo(const MyString& other) const; // C++ untypische Funktion: gibt -1, 0, 1 zurück MyString concat(char c) const; // hängt c ans Ende und gibt neuen String zurück size_t getLen() const; // return m_len MyString concat(const MyString& other) const; // Substring des Bereichs [beg, end) // falls beg ≥ m_len oder end ≤ beg: gibt leeren String zurück MyString substring(size_t beg, size_t end) const; // erzeugt 0-terminierten C-String, kopiert Inhalt und gibt Zeigerobjekt zurück unique_ptr<char[]> toCString() const; void myprint() const; size_t slen(const char* other) const; // Gleichheitsoperator (Inline-Implementation schon gegeben) bool operator==(const MyString& s) const { return compareTo(s) == 0; } // Ausgabe-Operator für Output-Streams (Inline-Implementation schon gegeben) friend ostream& operator<<(ostream& os, const MyString& s) { const size_t end = s.m_start + s.m_len; const char* const sc = s.m_string.get(); for(size_t i=s.m_start; i < end; i++) os << sc[i]; return os; } // Klassen-Methode static MyString valueOf(int i); // erzeugt eine String-Repräsentation von i }; #endif /* MYSTRING_H_ */
παπι Δημοσ. 27 Οκτωβρίου 2013 Δημοσ. 27 Οκτωβρίου 2013 Με πεθανε το "κλασεν μεθοντε". initialize και τελεος το κανεις με δηλωση const. Αν θες απλα να απενεργοποιησεις τον assignment, τοτε δηλωσε τον private.
pmav99 Δημοσ. 28 Οκτωβρίου 2013 Δημοσ. 28 Οκτωβρίου 2013 Εκτός και αν σου τα ζητάνε διαφορετικά, μάθε να γράφεις σχόλια στα αγγλικά.
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα