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

C++ type converter constructor


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

Δημοσ.

Έχω μια 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* [] και υπαρχει ασυμβατοτητα τυπων. Πως μπορω να το περασω αυτο?

Δημοσ. (επεξεργασμένο)

Τα εχεις ψιλομπερδεψει.

1) Δεν υπαρχει type conversion constructor

2) το shared_ptr ειναι smart pointer. Δες λιγο στο google ποια ειναι η δουλεια του.

 

Αν θες να βοηθησω, γραψε λιγο ποια συμπεριφορα θελεις απο αυτο το object.

 

edit: Μαλλον εγω τα εχω μπερδεψει.... Υπαρχει conversion constructor, απλα το εχω στο μυαλο μου με αλλη ορολογια (implicit/explicit constructor)

Επεξ/σία από παπι
Δημοσ.

Αυτος ο 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[]>.

Δημοσ.

Καμια σχεση. Και τα δυο (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

Δημοσ.

ναι αυτο που λες μας το εχουν σαν εναλλακτικη, αλλα γραφουνε να χρησιμοποιησοθμε την εντολη με το unique οπως εγραψα πιο πανω.. αλλα ακομα δεν εχω καταλαβει πως θα αποθηκευσω το m_string σε αυτον τον constructor

Δημοσ. (επεξεργασμένο)

Τι πανε και σας βαζουν...

Θα το περασεις ετσι

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, εισαι σε ξενω ΑΕΙ; Μου κανει μεγαλη εντυπωση αυτα που σας μαθαινουν.

Επεξ/σία από παπι
Δημοσ.
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());
}
};
Δημοσ.

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.
 

Δημοσ.

για να μην μπορει να αλλαξει τιμες ενα αντικειμενο του 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_ */



 

 

 

 

Δημοσ.

Με πεθανε το "κλασεν μεθοντε".

 

initialize και τελεος το κανεις με δηλωση const. Αν θες απλα να απενεργοποιησεις τον assignment, τοτε δηλωσε τον private.

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...