Помогни ни да направим Uroci.net по - богат! Добави урок
Категории Други уроци Adobe Photoshop Adobe Illustrator Adobe Flash Adobe Fireworks DreamWeaver CSS и HTML Corel Draw Image Ready PHP SEO CMS Microsoft Windows Microsoft Word Microsoft Excel PowerPoint Microsoft Access Microsoft Publisher Linux Visual basic JavaScript Ajax 3ds Max Maya 3D C++
C++
Sound Forge Gimp SWiSH

C++ част.7 (Член функции на клас)

C++ » C++
fix3d   трудност:    видян: 7543



7.3. Презареждане на оператор


В предишния раздел дефинирахме член данните и член функциите, необходими за инициализирането и освобождаването на обекти от класа String. Какви други функции трябва да бъдат дефинирани за класа Stirng?

Потребителят трябва да може да проверява обектите на класа Stirng: Дали един низ е празен? Равен ли е един низ на друг? Дали един низ е подниз на друг? Потребителят трябва също да може да въвежда обекти низове, да присвоява един низ на друг, да слепва два низа, да определя дължината на низ, да индексира съдържанието на низ и да преглежда съдържанието му. Кодирането на използуването на един низ може да изглежда така:

String inBuf;
while ( readString( cin, inBuf ))
{ if ( inBuf.isEmpty() ) return;
if ( inBuf.isEquаl( "done" )) return;
switch( inBuf.index(0) ) { /* ... */ }
cout << "String is ";
writeString( cout, inBuf ); }

Използуването на един клас не е толкова лесно колкото използуването на вградените типове данни. Например, имената избрани за операциите на String, въпреки че са логични и мнемонични, не са лесни за запомняне. Обратно, ето един кодов фрагмент, който използува презаредими представители на операторите, заменящи именуваните операции на String:

String inBuf;
while ( cin >> inBuf )
{ if ( !inBuf ) return;
if ( inBuf == "done" ) return;
switch( inBuf[ 0 ] ) { /* ... */ }
cout << "String is " << inBuf; }

В останалата част на този раздел ще реализираме набор от оператори, необходими за поддържането на този стил на програмиране за класа String.

Преглед на операторите за презареждане

Един проектант на клас може да предложи определен набор от оператори за работа с обекти на клас. Един оператор функция не е необходимо да бъде член функция, не трябва да получава поне един аргумент от тип клас. Това предпазва програмиста от предефиниране на оператори за вградените типове данни. Един оператор функция се дефинира по същия начин, както и обичайните функции, с изключение на това, че името им трябва да се състои от ключовата дума operator, следвана от някой предварително дефиниран от С++ оператор. Например,

String& String::Operator=( const String& s )
{ // assign one String object to another
len = s.len;
delete str; // deallocate existing array
str = new char[ len + 1 ];
strcpy( str, s.str );
return *this; }

При всяко присвояване на един обект от тип String на друг ще бъде викан оператора за присвояване на String.

#include "String.h"
String article( "the" );
String common;
main()
{ // String::Operator=()
common = article; }

Оператор функциите на един клас могат да бъдат презареждани при условие, че сигнатурата им е различна. Например, потребителите на нашия клас String трябва да бъдат в състояние да присвояват на обект от тип String стойност от тип char*.

class String
{
public:
String &operator=( const String& );
String &operator=( const char* );
// ...
};

strcmp() е стандартна библиотечна функция за сравняване на два символни низа за равенство. Ето нашия оператор за равенство на класа String, който работи с два String обекта:

String::Operator==( String& st )
{ // strcmp return 0 if both strings are equal
// operator== returns 1 for equality
return( strmcp( str, st.str ) == 0 );}



Дефиниране на оператор функции

Могат да бъдат презареждани само предварително дефинирани в С++ оператори. Проектантът на един клас не може да въведе нов оператор (“**”, например, за повдигане на степен). Таблица 7.1 показва операторите, които могат да бъдат презареждани. -Їя


Презаредими оператори
+ - * / % ^ & | ~ ! ‘
= < > <= >= ++ -- << >> == != &&
|| += -= /= %= ^= &= |= <<= >>= []
() -> ->* new delete


Предварително дефинираното значение на един оператор за вградените типове данни не може да бъде припокрито. Например, вградената операция за събиране на цели числа не може да бъде заменена с операция, която проверява за препълване. Нито пък може да бъде дефиниран допълнителен оператор за вградените типове данни. Събирането на цели масиви, например, не може да бъде добавено към набора от операции. Програмистът може да дефинира оператори само за типа клас. Това е предизвикано от изискването, че един оператор функция трябва да получи поне един аргумент от тип клас. Предварително дефинирания приоритет на операторите (раздел 3.9 разглежда това) не може да бъде променян. Независимо от типа на класа и реализацията на оператора,

x == y + z;

винаги ще изпълнява operator+ преди operator==. Както и при предварително дефинираните оператори приоритетът може да бъде променен чрез използуване на скоби.

Предварително дефинираната “арност” на оператора трябва да бъде запазена. Унарният логически оператор NOT (“!”), например, не може да бъде дефиниран като бинарен оператор за неравенство на два обекта от класа String. Неправилна е следната реализация:

// illegal: ! is a unary operator
operator!( String st1, String st2 )
{ return( strcmp(st1.str, st2.str ) != 0 ); }

Четири предварително дефинирани оператора (“+”, “-“, “*” и “&”) притежават както унарни, така и бинарни представители. Могат да бъдат дефинирани оператори с всяка от двете арности.

Може да има само по един представител на унарното увеличаване или намаляване с единица (“++”, “—“). При презареждане не се прави разлика между префиксния и постфиксния представител на тези оператори.

Въобще, един оператор функция може да бъде дефиниран като член или не член функция. Например, за поддържане на слепване на два обекта на класа String,

String st1( "cobble" );
String st2( "stone" );
String st3 = st1 + st2;

може да бъде дефиниран оператор за събиране или като нечлен приятел на Stirng:

class String { friend String& operator+( String&, String& );
// ... };

или като негова член функция:

class String { public: String& operator+( String& );
// ... };

Дефинирането и на двата представителя вероятно ще предизвика двусмислие:

class String
{ friend String& operator+( String&, String& );
public: String& operator+( String& );
// ... };

String a( "hobby" ), b( "horse" );
String c = a + b; // error: anbiguous

Член функцията на един клас винаги дефинира аргументи операнди с един по-малко от една функция приятел. Това се дължи на факта, че първият операнд на член функцията се задава неявно като обекта на класа, за който тя е извикана. Например,

st1 + st2

може да бъде дефиниран като член функция със следната форма:

st1.operator+( st2 )

или като нечлен функция с формата:

operator+( st1, st2 )

Не може да се зададат и двете дефиниции, понеже компилаторът не би могъл да прави избор между тях.

Съществуват четири оператор функции, които трябва да бъдат дефинирани като член функции на клас: оператора за присвояване (“=”), индексния оператор (“[]”), оператора за обръщение (“()”) и оператора указател за избор на член (“->”). Тези оператори се обсъждат индивидуално следващите подраздели на тази глава.

Една член функция на клас изисква обект от класа си за ляв операнд. Операция, която не изисква за ляв операнд обект на клас трябва да бъде дефинирана като не член. Ако функцията изисква достъп до не публичните членове на клас, тя също трябва да бъде декларирана като приятелска. Например,

class String {
friend ostream& operator<<( ostream& os, String& s )
{ return ( os << s.str ); }
// ... };

Упражнение 7-11. Декларирайте прототипа на унарната оператор функция operator+() - първо като приятел не член и след това като член функция на класа String.
Упражнение 7-12. Логическият оператор NOT връща 1 ако обектът на String е празен; иначе връща 0. Реализирайте го като оператор на String.
Упражнение 7-13. Бинарната оператор функция operator+() слепва два обекта на String. Реализирайте този оператор като не член.
Упражнение 7-14. Реализирайте представител на operator+() като член функция на String.

Оператор []

Потребителите на нашия клас String желаят да имат достъп за четене и запис до конкретните символи на члена на класа str. Ние трябва да поддържаме следния начин на използуване на обектите на класа String:

String sentence( "Ash on an old man’s sleeve." );
String tempBuf( sentence.getLen() );
for ( int i = 0; i < sentence.getLen(); ++i )
tempBuf[ i ] = sentence[ i ];
String::getLen() е една проста функция за достъп, която връща дължината на обекта на String:
inline String::getLen() { return len; }

Индексният оператор трябва да може да се записва както от лявата, така и от дясната страна на един ираз. За да бъде постигнато това връщаната от него стойност трябва да бъде стойност за запис. Тази стойност може да баде дефинирана от тип псевдоним:

inline char& String::Operator[]( int elem )
{ checkBounds( elem );
return str[ elem ]; }

Връщаната от индексния оператор стойност е стойността за запис на индексния елемент. Тя може да се явява и от лявата страна на оператор за присвояване. Например,

String st( "mauve" );
st[0] = ‘M’;

присвояване на стойността на константа на нулевия елемент на st.str.

checkBounds() проверява дали изпратения чрез индексния оператор индекс е в границите на масива на String. Ако не е се издава съобщениеза грешка и се прекъсва програмата. Реализацията изглежда така:

// pull in exit(int) prototype
#include <stdlib.h>
void String::checkBounds( int elem )
{ // check array bounds
if ( elem < 0 || elem >= len )
{ cerr << "nString Array Out of Bounds! index: " << elem << " string length (0-" << len-1 << ")n";
exit( -1 ); } }


Страници: «3 4 5 6 7 8 9 »

Регистрирайте се, за да добавите коментар

реклама

© Всички права запазени. 2006-2008. Created by: Site.bg
Препоръчваме: IT Новини | Кино и игри | Диплома.бг | Paparak.bg | Тунинг Портал | uchenik.com | TRAVEL туризъм | Реферати | AmAm.bg | Иде.ли | Курсови работи | AnimeS-bg.com | Фото Форум | Запознанства | Мрежа от приятели | IT Light | Spodeli.net | Фото-Култ | IDG.BG | Teenproblem.net | Блог - Образование | Fresh-BG.com | Hanovete.com | Bulfleet.com | Mythlands.com | Ohoboho.com | Казанлък.Com | News24 | Setcom.bg | Atol.bg | Elmaz.com | MobileBulgaria.com