Помогни ни да направим Uroci.net по - богат! Добави урок

C++ част.6 (Класове)

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



6.8. Обхват на клас

Всеки клас допуска както глобален така и локален обхват. Въпреки, че дефиницията на един клас може да бъде вложена в дефиницията на друг, двата класа се разглеждат като притежаващи един обхват. Вложеният клас не се счита за член на външния клас и няма никакви специални привилегии за достъп до непубличните членове на този клас. Например, в раздел 4.2 се дефинира IntList и личния клас IntItem. Ето една еквивалентна дефиниция, при която дефиницията на IntItem е вложена в дефиницията на IntList:

class IntList

{

class IntItem

{ friend class IntList;

private: IntItem(int v=0) { val = v; next = 0; }

IntItem *next;

int val;

};

public: IntList(int val) { list = new IntItem( val );

}

IntList() { list = 0 }

// ... private:

IntItem *atEnd();

IntItem *list;

};

IntItem не е нито член, нито личен член на Intlist. list, един обект на класа IntItem е личен член на IntList. Както IntItem, така и IntList имат файлов обхват. IntItem е лексикално вложен в IntList за да показва на читателя, че се използува само от IntList.

За спецификации typedef, които се намират в дефиницията на класа също се счита, че имат обхвата на външния клас. Например,

class Foo {

typedef int Bar;

private:

Bar val;

// ok };

Bar val;

// ok: the typedef is visible

Всеки клас поддържа свой собствен обхват. За имената на членовете на класа се казва, че са локални за обхвата на класа си. Ако името на променлива с файлов обхват се използува от член на клас, тази променлива е скрита в обхвата на класа. Например,

int height;

class FooBar

{ public:

// FooBar::height <== 0

FooBar() { height = 0 }

private:

short height;

};

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

int height;

class FooBar;

public: FooBar() { height = ::height; }

private:

short height;

};

Обратното, една променлива, дефинирана във функция, не е видима до откриването на декларацията й. В следващия пример localFunc() работи с два различни представителя на height.

int height = 66;

localFunc() { int hi = height; // ::height

int height = 24; // hides ::height

hi = heigth;// hi <== 24

Следващият пример е още по-объркващ. За кой представител на height мислите, че става дума?

int height = 66;

bdPrac() { int height = ::height; }

Компилаторът вероятно няма да обърка двата представителя на порменливата; читателят на програмата обаче би могъл. Едно предпочитано в този случай решение е да се преименува локалният представител до нещо, различно от heigth. Всяка член функция се явява в обхват на класа си. Тя също поддържа свой собствен локален обхват, който наподобява този на нечлен функциите. Ако едно име на член на клас се използува в локалния обхват на дадена член функция, името на член на класа се скрива в точката, където се дефинира локалния представител. Например,

Screen::barPractice() {

int hi = height; // Screen::heigth

int heigth = height; // heigth local instance }

Достъп до скрития член на класа може да има през оператора за обхват на класа. Например,

Screen::bdPrac() { int height = Screen::height; }

Достъп до скрита глобална променлива е възможен и чрез оператора за обхват. Например,

Screen::bdPractice() {

int height = (Screen::height > ::height) ? ::height : Screen::heeight; }

Съглашения относно обхвата

Когато един идентификатор се явява в член функция на някой клас, алгоритъмът, който свързва идентификатора е следният:

1. Блокът, съдържащ даден идентификатор се претърсва за декларация на идентификатора. Ако такава бъде намерена идентификаторът се свързва; иначе се търси в по-външен обхват.

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

3. Ако блокът, в който се явява идентификатора е също член функция, по-външният обхват е този на класа. Ако един член на клас е деклариран със същото име, както и иднтификатора, то идентификатора се свързва така, че да се отнася за този член; иначе се търси по-външен обхват.

4. За свързването на идентификатор в член функция на даден клас като по-външен обхват се приема файловия, ако класът не е произлязъл от друг клас. Ако бъде намерена декларация, идентификаторът се свързва; иначе идентификаторът се отбелязва като недекларирана променлива.

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

extern f( int ), ff(), f3();

int i = 1024;

class Exsample

{ publlic:

f(); // hides ::f( int )

Example( int ii = 0 ){ i = ii; }

private:

int i; // hides ::i

int ff; // hides ::ff() }

Един идентификато е скрит когато името му се използува във вътрешен обхват дори когато типът на локалният представител е различен. Глобалните идентификатори i, ff() и F(int) са скрити в обхвата на класа Example. Във Example::f() обръщението към тези идентификатори трябва да бъде предшествано от файловия оператор за обхват.

#include "Example.h"

Example::f() { int j;

// error: file scope f() is hidden

// Exsample::f() takes no argument

j = f( 1 ); // ok: explicit refernce to ::

f( int ) // i is resolved to Example::i;

j = ::f( i );// ok: explicit reference is unnecessary

// file scope f3() is visible within Example

return( f3() ); }

Example::f() може също да дефинира локални представители на i и f. Тези локални представители ще скрият представителите на членовете на класа. За да работите с членовете на класа трябва да използувате оператора за обхват на клас.

#include "Example.h" Example::f()

{ // hides Example::i

int i = ff ? Example::i : ( ::ff() ? ::i : 0);

// error: Example::f3() undefined

return( Example::f3(); }

Локални класове

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

int doString( char *s)

{ // local class visible only within doString()

class String {...};

String str( s ); };

// error: String not visible

String str( "gravity" );

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

int doString( char *s )

{

class String

{ public: String& operator=(char*); };

Striing::Operator=(char* s) {} // illegal }

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

int stirng1(char *s)

{ class String { ... }; }

int string2(char *s)

{ class String { ... }; } // error: no Stirng class visible

String::Operator=(char* s) {}

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

Въпреки, че локалният клас е в обхвата на функцията, която го съдържа, променливите, дефинирани в обхвата на тази функция не са видими в член функциите на локалния клас. Например, bufSize в String се свързва с представителя, дефиниран с файлов обхват, докато bufSize в func() се свързва с локалния представител.

const int bufSize = 1024;

void func() {

const int bufSize = 512;

char *ps = new char[bufSize]; // 512

class String

{

public: String() {

str = new char[ bufSize ]; // 1024 !

} // ...

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


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

Сподели урока:



Коментари (1)

odissea на 19.02 2009 в 17:32ч.
добро - но прекалено дълго ... отказах се да го чета до края

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


Калдейта Ком ЕООД - © 2003-. Всички права запазени.
Препоръчваме: IT Новини