Клас Рядок h2>
Ось досить реалістичний приклад класу string. У ньому
проводиться облік посилань на рядок з метою мінімізувати копіювання і в
як констант застосовуються стандартні символьні рядки C + +. p>
# include p>
# include p>
class string ( p>
struct srep ( p>
char * s;// покажчик на дані p>
int n;// лічильник посилань p>
); p>
srep * p; p>
public: p>
string (char
*);// String x = "abc" p>
string ();// string x; p>
string (string
&);// String x = string ... p>
string &
operator = (char *); p>
string &
operator = (string &); p>
~ string (); p>
char &
operator [] (int i); p>
friend
ostream & operator <<(ostream &, string &); p>
friend
istream & operator>> (istream &, string &); p>
friend int
operator == (string & x, char * s) p>
(return
strcmp (x.p-> s, s) == 0;) p>
friend int
operator == (string & x, string & y) p>
(return
strcmp (x.p-> s, y.p-> s) == 0;) p>
friend int
operator! = (string & x, char * s) p>
(return
strcmp (x.p-> s, s)! = 0;) p>
friend int
operator! = (string & x, string & y) p>
(return
strcmp (x.p-> s, y.p-> s)! = 0;) p>
); p>
Конструктори і деструктори прості (як завжди): p>
string:: string () p>
( p>
p = new srep; p>
p-> s = 0; p>
p-> n = 1; p>
) p>
string:: string (char * s) p>
( p>
p = new srep; p>
p-> s = new
char [strlen (s) +1]; p>
strcpy (p-> s, s); p>
p-> n = 1; p>
) p>
string:: string (string & x) p>
( p>
x.p-> n ++; p>
p = x.p; p>
) p>
string:: ~ string () p>
( p>
if (- p-> n
== 0) ( p>
delete
p-> s; p>
delete p; p>
) p>
) p>
Як звичайно, операції привласнення дуже схожі на
конструктори. Вони повинні обробляти очищення свого першого (лівого) операнда:
p>
string & string:: operator = (char * s) p>
( p>
if (p-> n>
1) (//роз'єднати себе p>
p-n -; p>
p = new srep; p>
) p>
else if
(p-> n == 1) p>
delete
p-> s; p>
p-> s = new
char [strlen (s) +1]; p>
strcpy (p-> s, s); p>
p-> n = 1; p>
return * this; p>
) p>
розсудливо забезпечити, щоб призначення об'єкту
самому собі працювало правильно: p>
string & string:: operator = (string & x) p>
( p>
x.p-> n ++; p>
if (- p-> n
== 0) ( p>
delete
p-> s; p>
delete p; p>
) p>
p = x.p; p>
return * this; p>
) p>
Операція виводу задумана так, щоб продемонструвати
застосування обліку посилань. Вона повторює кожну що вводиться рядок (за допомогою
операції <<, яка визначається пізніше): p>
ostream & operator <<(ostream & s,
string & x) p>
( p>
return s
< s << "[" < n <<
"] n"; p>
) p>
Операція вводу використовує стандартну функцію введення
символьної рядка. p>
istream & operator>> (istream & s,
string & x) p>
( p>
char buf [256]; p>
s>> buf; p>
x = buf; p>
cout << "echo:" <
return s; p>
) p>
Для доступу до окремих символів надана операція
індексування. Здійснюється перевірка індексу: p>
void error (char * p) p>
( p>
cerr <
exit (1); p>
) p>
char & string:: operator [] (int i) p>
( p>
if (i <0 | |
strlen (p-> s) s [i]; p>
) p>
Головний програма просто трохи випробує дії над
рядками. Вона читає слова з введення в строки, а потім ці рядки друкує. Вона
продовжує це робити до тих пір, поки не розпізнає рядок done, яка
завершує збереження слів у рядках, або не зустріне кінець файлу. Після цього
вона друкує рядки у зворотному порядку і завершується. p>
main () p>
( p>
string x [100]; p>
int n; p>
cout <<
"звідси начнемn"; p>
for (n = 0;
cin>> x [n]; n + +) ( p>
string y; p>
if
(n == 100) error ( "занадто багато рядків "); p>
cout
<<(y = x [n ]); p>
if (y == "done") break; p>
) p>
cout <<
"звідси ми пройдемо обратноn"; p>
for (int i = n-1; 0 <= i; i -) cout <<
x [i]; p>
) p>
Список літератури h2>
Для підготовки даної роботи були використані матеріали
з сайту http://www.realcoding.net
p>