Форум программистов, компьютерный форум CyberForum.ru

Свой класс String - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 10, средняя оценка - 4.70
Gepar
 Аватар для Gepar
1173 / 529 / 20
Регистрация: 01.07.2009
Сообщений: 3,508
29.09.2011, 17:37     Свой класс String #1
Небольшой набросок на класс String
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include <iostream>
#include <cstring>
using namespace std;
 
class String
{
    struct Srep;//представление
    Srep *rep;
    class Cref;//ссылка на char
 
    public:
    class Range{};//исключения
    String();//x=""
    String (const char*);//x="abc"
    String (const String&);//x=other_string
    String& operator=(const char*);
    String& operator=(const String&);
 
    void check(int i) const
    {
        if(i<0 || (rep->sz)<=i) throw Rangee(); //ОШИБКА ОШИБКА ОШИБКА
    }
 
    char read(int i) const {return rep->s[i];}
    void write(int i,char c){rep=rep->get_own_copy();rep->s[i]=c;}
    Cref operator[](int i){check(i);return Cref(*this,i);}
    char operator[](int i) const{check(i);return rep->s[i];}
    int size() const{return rep->sz;}
    ~String();
};
 
class String::Srep
{
public:
    char *s;//указатель на элемент
    int sz;//кол-во символов
    int n;//счётчик символов
 
    Srep(int nsz, const char *p)
    {
        n=1;
        sz=nsz;
        s=new char[sz+1];
        strcpy(s,p);
    }
 
    ~Srep(){delete []s;}
 
    Srep* get_own_copy()
    {
        if(n==1) return this;
        n--;
        return new Srep(sz,s);
    }
 
    void assign(int nsz, const char* p)
    {
        if (sz!=nsz)
        {
            delete[] s;
            sz=nsz;
            s=new char[sz+1];
        }
        strcpy(s,p);
    }
    private:
    Srep (const Srep&);
    Srep& operator=(const Srep&);
};
 
String::String()
{
    rep=new Srep(0,"");
};
 
String::String(const String& x)
{
    x.rep->n++;
    rep=x.rep; //разделяемое представление
};
 
String::~String()
{
    if(--rep->n==0) delete rep;
};
 
String &String::operator=(const String &x)
{
    x.rep->n++;//защита от "st=st"
    if(--rep->n==0) delete rep;
    rep=x.rep;
    return *this;
};
 
String::String(const char* s)
{
    rep=new Srep(strlen(s),s);
};
 
String& String::operator=(const char *s)
{
    if(rep->n==1)
     rep->assign(strlen(s),s); //используем старый Srep
    else
    {
        rep->n--;
        rep=new Srep(strlen(s),s);//используем новый Srep
    }
    return *this;
};
 
class String::Cref
{
    friend class String;
    String &s;
    int i;
    Cref(String & ss, int ii):s(ss),i(ii){}
    Cref(const Cref& r):s(r.s),i(r.i){}
    Cref();
 
public:
    operator char() const{s.check(i);return s.read(i);}//выдаёт значение
    void operator=(char c) {s.write(i,c);}
};
 
 
 
 
 
 
 
int main()
{
 
}
Беда в том что компилятор ругается на реализацию функции void check, мол нельзя использовать там структуру Srep, но почему же нельзя когда я в начале класса сделал объявление её, а после описания класса описал её так чего же тогда компилятору не так? + так же компилятор ругается на исключение Rangee, хотя мне тоже непонятно почему, ведь оно тоже было выше объявлено и определено.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Net_Wanderer
235 / 208 / 19
Регистрация: 08.06.2011
Сообщений: 467
29.09.2011, 17:53     Свой класс String #2
Цитата Сообщение от Gepar Посмотреть сообщение
мол нельзя использовать там структуру Srep, но почему же нельзя когда я в начале класса сделал объявление её
Это только обьявление, вы сказали компилятору что это тип; но к этому моменту компилятор ничего не знает о полях и методах класса Srep, по этой же причине можно создать только указатель на Srep, а объект нет, потому как комилятор не знает сколько памяти выделить под объект, а у указателей размер фиксированный.
т.е. в строке rep->sz компилятор не знает что такое sz
Gepar
 Аватар для Gepar
1173 / 529 / 20
Регистрация: 01.07.2009
Сообщений: 3,508
29.09.2011, 18:01  [ТС]     Свой класс String #3
Net_Wanderer, как же я тогда могу определить мой класс Srep? Перенести выше определения класса String я не могу, внизу оставить как оказалось тоже, если поместить его внтури то слишком много место займёт, а в отдельный .h файл добавлять тоже лень. Как же тогда дать компилятору понять что класс Srep внизу определён и у него есть все нужные поля?
OstapBender
 Аватар для OstapBender
581 / 519 / 35
Регистрация: 22.03.2011
Сообщений: 1,585
29.09.2011, 18:26     Свой класс String #4
сделай вложенным полем

либо функцию check определи после определения Srep
Net_Wanderer
235 / 208 / 19
Регистрация: 08.06.2011
Сообщений: 467
29.09.2011, 19:19     Свой класс String #5
Цитата Сообщение от Gepar Посмотреть сообщение
компилятор ругается на исключение Rangee
C++
1
    class Range{};//исключения
if(i<0 || (rep->sz)<=i) throw Rangee();

И ещё у вас с Cref такая же проблема как и с Srep, только сложнее
C++
1
Cref operator[](int i){check(i);return Cref(*this,i);}
возвращаемое значение operator[] это обьект Cref и определение его после определения Cref не поможет
Gepar
 Аватар для Gepar
1173 / 529 / 20
Регистрация: 01.07.2009
Сообщений: 3,508
29.09.2011, 20:20  [ТС]     Свой класс String #6
Ладно, допустим насчёт того Srep понял, сейчас попробую поправить, а насчёт Rangee всё равно не понял, с ним то что не так? Обычный класс для исключений, он полностью определён до того как я захотел его выбросить так что же не нравится компилятору?

Добавлено через 13 минут
А, уже понял, у меня там название у исключения чуть другое. Вот перетащил определения тех классов и получилось так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include <iostream>
#include <cstring>
using namespace std;
 
class String
{
class Srep
    {
    public:
        char *s;//указатель на элемент
        int sz;//кол-во символов
        int n;//счётчик символов
 
        Srep(int nsz, const char *p)
        {
            n=1;
            sz=nsz;
            s=new char[sz+1];
            strcpy(s,p);
        }
 
        ~Srep(){delete []s;}
 
        Srep* get_own_copy()
        {
            if(n==1) return this;
            n--;
            return new Srep(sz,s);
        }
 
        void assign(int nsz, const char* p)
        {
            if (sz!=nsz)
            {
                delete[] s;
                sz=nsz;
                s=new char[sz+1];
            }
            strcpy(s,p);
        }
        private:
        Srep (const Srep&);
        Srep& operator=(const Srep&);
    };
 
    class Cref
    {
        friend class String;
        String &s;
        int i;
        Cref(String & ss, int ii):s(ss),i(ii){}
        Cref(const Cref& r):s(r.s),i(r.i){}
        Cref();
 
    public:
        operator char() const{s.check(i);return s.read(i);}//выдаёт значение
        void operator=(char c) {s.write(i,c);}
    };
 
 
    Srep *rep;
 
public:
    class Range{};//исключения
    String();//x=""
    String (const char*);//x="abc"
    String (const String&);//x=other_string
    String& operator=(const char*);
    String& operator=(const String&);
 
    void check(int i) const;
 
    char read(int i) const {return rep->s[i];}
    void write(int i,char c){rep=rep->get_own_copy();rep->s[i]=c;}
    Cref operator[](int i){check(i);return Cref(*this,i);}
    char operator[](int i) const{check(i);return rep->s[i];}
    int size() const{return rep->sz;}
    ~String();
};
 
String::String()
{
    rep=new Srep(0,"");
};
 
String::String(const String& x)
{
    x.rep->n++;
    rep=x.rep; //разделяемое представление
};
 
String::~String()
{
    if(--rep->n==0) delete rep;
};
 
String &String::operator=(const String &x)
{
    x.rep->n++;//защита от "st=st"
    if(--rep->n==0) delete rep;
    rep=x.rep;
    return *this;
};
 
String::String(const char* s)
{
    rep=new Srep(strlen(s),s);
};
 
String& String::operator=(const char *s)
{
    if(rep->n==1)
     rep->assign(strlen(s),s); //используем старый Srep
    else
    {
        rep->n--;
        rep=new Srep(strlen(s),s);//используем новый Srep
    }
    return *this;
};
 
void String::check(int i) const
{
    if(i<0 || (rep->sz)<=i) throw String::Range();
};
 
 
 
 
 
 
 
int main()
{
 
}
Yandex
Объявления
29.09.2011, 20:20     Свой класс String
Ответ Создать тему
Опции темы

Текущее время: 06:10. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru