Объявления вложенных классов
Класс можно объявить в области другого класса. Такой класс называется вложенным классом. Вложенные классы считаются в пределах область включаемого класса и доступны для использования в рамках этого область. Для обращения ко вложенному классу из области, отличной от непосредственно включающей его области, следует использовать полное имя.
В следующем примере показано, как объявить вложенные классы.
// nested_class_declarations.cpp class BufferedIO < public: enum IOError < None, Access, General >; // Declare nested class BufferedInput. class BufferedInput < public: int read(); int good() < return _inputerror == None; >private: IOError _inputerror; >; // Declare nested class BufferedOutput. class BufferedOutput < // Member list >; >; int main()
BufferedIO::BufferedInput и BufferedIO::BufferedOutput объявляются в BufferedIO пределах . Эти имена классов не видимы за пределами области класса BufferedIO . Однако объект типа BufferedIO не содержит объекты типа BufferedInput или BufferedOutput .
Вложенные классы могут непосредственно использовать имена, имена типов, имена статических членов и перечислители только из включающего класса. Для использования имен других членов класса необходимо использовать указатели, ссылки или имена объектов.
В предыдущем примере BufferedIO к перечислению IOError можно получить доступ непосредственно с помощью функций-членов во вложенных классах BufferedIO::BufferedInput или BufferedIO::BufferedOutput , как показано в функции good .
Вложенные классы объявляют только типы в пределах области класса. Они не создают объекты по вложенном классе. В предыдущем примере объявляется два вложенных класса, но не объявляются объекты этих типов классов.
Исключением из видимости области объявления вложенного класса является объявление имени типа вместе с опережающим объявлением. В этом случае имя класса, объявленное с помощью опережающего объявления, видимо за пределами включающего класса, при этом область определена как наименьшая включающая область вне класса. Например:
// nested_class_declarations_2.cpp class C < public: typedef class U u_t; // class U visible outside class C scope typedef class V <>v_t; // class V not visible outside class C >; int main() < // okay, forward declaration used above so file scope is used U* pu; // error, type name only exists in class C scope u_t* pu2; // C2065 // error, class defined above so class C scope V* pv; // C2065 // okay, fully qualified name C::V* pv2; >
Права доступа во вложенных классах
Вложение класса в другой класс не предоставляет особые права доступа к функциям-членам вложенного класса. Аналогичным образом, функции-члены включающего класса не имеют особых прав доступа к членам вложенного класса.
Функции-члены во вложенных классах
Функции-члены, объявленные во вложенных классах, могут быть определены в области файла. Предыдущий пример можно было бы записать следующим образом:
// member_functions_in_nested_classes.cpp class BufferedIO < public: enum IOError < None, Access, General >; class BufferedInput < public: int read(); // Declare but do not define member int good(); // functions read and good. private: IOError _inputerror; >; class BufferedOutput < // Member list. >; >; // Define member functions read and good in // file scope. int BufferedIO::BufferedInput::read() < return(1); >int BufferedIO::BufferedInput::good() < return _inputerror == None; >int main()
В предыдущем примере синтаксис с полным именем типа используется для объявления имени функции. Объявление:
BufferedIO::BufferedInput::read()
означает » read функция, являющаяся членом BufferedInput класса, который находится в область BufferedIO класса». Так как в этом объявлении используется синтаксис имени квалифицированного типа, возможны конструкции следующей формы:
typedef BufferedIO::BufferedInput BIO_INPUT; int BIO_INPUT::read()
Предыдущее объявление эквивалентно предыдущему, но вместо имен классов используется typedef имя.
Дружественные функции во вложенных классах
Считается, что дружественные функции, объявленные во вложенном классе, находятся в области вложенного, а не включающего класса. Поэтому дружественные функции не получают особых прав доступа к членам или функциям-членам включающего класса. Если требуется использовать имя, объявленное во вложенном классе, в дружественной функции, и дружественная функция определена в области видимости файла, используйте полные имена типов, как показано ниже.
// friend_functions_and_nested_classes.cpp #include enum < sizeOfMessage = 255 >; char *rgszMessage[sizeOfMessage]; class BufferedIO < public: class BufferedInput < public: friend int GetExtendedErrorStatus(); static char *message; static int messageSize; int iMsgNo; >; >; char *BufferedIO::BufferedInput::message; int BufferedIO::BufferedInput::messageSize; int GetExtendedErrorStatus() < int iMsgNo = 1; // assign arbitrary value as message number strcpy_s( BufferedIO::BufferedInput::message, BufferedIO::BufferedInput::messageSize, rgszMessage[iMsgNo] ); return iMsgNo; >int main()
В следующем коде показана функция GetExtendedErrorStatus , объявленная в качестве дружественной функции. В функции, определенной в области видимости файла, сообщение копируется из статического массива в член класса. Обратите внимание, что для оптимальной реализации функции GetExtendedErrorStatus рекомендуется объявить ее следующим образом.
int GetExtendedErrorStatus( char *message )
В предыдущем интерфейсе несколько классов могут использовать службы этой функции, передав адрес памяти, в которую требуется скопировать сообщение об ошибке.
Использование одного класса в другом
Здравствуйте,
у менят есть класс «А» и есть класс «В». Проблема: Класса «А» работает с comPORT объявить я классе «В» я могу его только 1 раз. Вопрос: Как в методах класса «В» мне использовать методы из класса «А» для остылки информации?
Отслеживать
371 1 1 золотой знак 5 5 серебряных знаков 13 13 бронзовых знаков
задан 21 июн 2014 в 14:02
11 1 1 бронзовый знак
Какой-то бессвязный набор слов. Попробуйте переформулировать ваш вопрос, что ли.
21 июн 2014 в 14:07
@foxmen, небольшой пример Вашего кода (классы A, B и их создание в программе) не помешает.
21 июн 2014 в 14:46
@foxmen, Перефразируйте, пожалуйста, Ваш вопрос: исправьте грамматические ошибки, правильно расставьте запятые. Если ещё добавите побольше уточняющей информации, то Вы ускорите получение ответа.
21 июн 2014 в 19:07
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
Pettern Registry как вариант.
Отслеживать
ответ дан 21 июн 2014 в 19:17
Eugene Smiths Eugene Smiths
89 1 1 серебряный знак 9 9 бронзовых знаков
или я ничего не понял вообще. this
21 июн 2014 в 19:27
@Eugene Smiths, Постарайтесь писать более развернутые ответы. Поясните, на чем основано ваше утверждение.
23 июн 2014 в 7:06
Если я правильно вас понимаю, вам пригодится forward declaration и указатели на экземпляры нужных классов
// header_a.h class B; class A < B *bObj_; //. >; // header_b.h class A; class B < A *aObj_; //. >;
Отслеживать
ответ дан 22 июн 2014 в 13:29
8,656 1 1 золотой знак 16 16 серебряных знаков 32 32 бронзовых знака
- классы
- c++
-
Важное на Мете
Похожие
Подписаться на ленту
Лента вопроса
Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.
Дизайн сайта / логотип © 2024 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2024.1.3.2953
Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.
Как использовать переменную из одного класса в другом с помощью указателей?
Я давно не живу в русско язычной стране, так что могут быть ошибки.
У меня такая проблема.
Мне надо создать два класса и третьим классом этими двумя классами управлять. Но у меня ни чего не получается.
Вот пример.
class car
privat:
int KmReport
public
void setKmReport()
getKmReport(void)
>;
class Drive
public:
int drive_length(* Car);
>;
Вот у нас есть класс Car и в ней в private есть переменная KmReport (то есть сколько км машина проехала). C помощью get и set я добираюсь до этой переменной.
Класс drive своего рода управляющий. То есть при введение drive_length через cin я должен изменить проеденный путь в классе Car.
1. Вопрос должен быть class drive , friend class?
void Auto::setKmReport()
KmReport =0 // машина не сколько не проехала первоначально
>
Auto::getKmReport(void)
return KmReport;
>
// с этого момента я не увер что я делаю.
int Drive::drive_length(*Car)
int value;
cout cin >> value;
// если это вообще правильно(все выше стоящие)
>
C++. Ссылки на объект класса. Доступ к объекту класса по ссылке. Ссылки как члены данных класса. Примеры
Ссылки на объект класса. Доступ к объекту класса по ссылке. Ссылки как члены данных класса. Примеры
Поиск на других ресурсах:
1. Как объявляется переменная, которая есть ссылкой на класс? Как объявить ссылку на объект класса?
Ссылка на класс объявляется с помощью символа & . При объявлении переменной, которая есть ссылкой, необходимо сразу ее инициализировать значением объекта, для которого уже выделена память.
Общий вид объявления ссылки на объект класса имеет вид:
CMyClass & ref = obj;
- CMyClass – имя класса;
- ref – имя переменной, которая есть ссылкой на объект obj ;
- obj – имя объекта, для которого выделена память.
2. Пример объявления ссылки на объект класса и ее использование
Пусть задан класс CYear , реализующий год. Объявление класса имеет следующий вид:
// класс, реализующий категорию "Год" class CYear < int year; // внутренняя переменная public: CYear(void); // конструктор по умолчанию // конструктор с 1 параметром CYear(int year) < this->year = year; > // методы доступа int Get(void) < return year; > void Set(int year) < this->year = year; > // метод, определяющий високосный год или нет bool IsLeapYear(void); >; // конструктор по умолчанию CYear::CYear(void) < year = 2000; // начальная инициализация > // метод, определяющий високосный год или нет bool CYear::IsLeapYear(void) < if (year % 400 == 0) return true; else if (year % 100 == 0) return false; else if (year % 4 == 0) return true; else return false; >
Использование класса в другом методе
CYear c1; // c1 - объект CYear & c2 = c1; // c1 и c2 указывают на один и тот же участок памяти int d; // доступ к объекту c1 c1.Set(2010); d = c1.Get(); // d = 2010 // доступ по ссылке c2 d = c2.Get(); // d = 2010 c2.Set(3333); d = c1.Get(); // d = 3333; c1 и c2 указывают на один и тот же участок памяти
В вышеприведенном коде с помощью символа & объявляется переменная-ссылка c2 на объект класса c1 с помощью следующей строки
CYear & c2 = c1;
Для переменной c1 память уже выделена. Переменные c1 и c2 ссылаются на один и тот же участок памяти (на один и тот же объект).
3. Объявление и использование ссылки на объект класса, доступ к которому осуществляется с помощью неуправляемого ( unmanaged ) указателя. Пример
Если объявить указатель на класс ( * ) и выделить для него память, то на этот участок памяти (объект) можно объявить ссылку.
Нижеследующий пример демонстрирует использование указателя и ссылки на класс CYear, что описывается в п. 2.
CYear * pc = new CYear(); // неуправляемый указатель, выделяется память CYear & rc = (*pc); // ссылка на память, выделенную для указателя int d; // доступ к объекту по указателю pc->Set(2040); d = pc->Get(); // d = 2040 d = rc.Get(); // d = 2040 rc.Set(2100); d = pc->Get(); // d = 2100
4. Пример использования ссылки на объект класса, которая есть членом данных другого класса. Что произойдет, если в классе не инициализировать ссылку на объект?
Ссылка (переменная-ссылка) на объект класса может быть членом данных другого класса. При объявлении переменной-ссылки в классе, эта переменная может быть тут же инициализирована в специально разработанном конструкторе. В этом случае для переменной-ссылки класса память выделяется динамически (см. пример ниже).
В примере ниже демонстрируется применение класса CLine (отрезок), в котором объявляются две ссылки на класс CPoint , который описывает точку на координатной плоскости.
В классе CPoint реализованы следующие члены данных и методы:
- внутренние переменные x , y – координаты точки;
- конструктор по умолчанию;
- методы доступа GetXY() , SetXY() .
В классе CLine объявляются следующие члены данных и методы:
- внутренние переменные-ссылки типа CPoint& (ссылка на объект класса CPoint ) с именами p1 , p2 ;
- конструктор с двумя параметрами, который динамично инициализирует ссылки p1 , p2 при объявлении объекта класса;
- методы доступа GetPoints() , SetPoints() .
Объявление классов CPoint и CLine имеет следующий вид:
// класс, реализующий точку class CPoint < int x,y; public: // конструктор по умолчанию CPoint() < x = y = 0; >// методы доступа void GetXY(int* nx, int* ny) < *nx = x; *ny = y; >void SetXY(int nx, int ny) < x = nx; y = ny; >>; // класс, реализующий отрезок class CLine < // ссылки на объекты типа CPoint CPoint & p1; CPoint & p2; public: // конструктор по умолчанию // динамически инициализируются значения ссылок p1 и p2 CLine():p1(* new CPoint), p2(* new CPoint) < p1.SetXY(0, 0); p2.SetXY(1, 1); >// методы доступа // вернуть координаты точек void GetPoints(CPoint* pt1, CPoint* pt2) < int x, y; p1.GetXY(&x, &y); // взять значения x, y для точки p1 pt1->SetXY(x, y); // установить x,y в новую точку pt1 p2.GetXY(&x, &y); // взять x,y pt2->SetXY(x, y); // записать x,y в pt2 > // установить новые значения точек void SetPoints(CPoint* pt1, CPoint* pt2) < int x, y; // p1 => pt1 p1.GetXY(&x, &y); pt1->SetXY(x, y); // p2 => pt2 p2.GetXY(&x, &y); pt2->SetXY(x, y); > >;
Важно: при объявлении ссылки на объект некоторого класса, обязательно нужно инициализировать эти ссылки некоторым значением, например, в специально разработанном конструкторе по умолчанию. Если не указать код инициализации ссылки в конструкторе, то компилятор выдаст ошибку:
p1' : must be initialized in constructor base/member initializer list .
В классе CLine осуществляется динамическая инициализация ссылок p1 и p2 с помощью конструктора:
// динамическая инициализация переменных-ссылок p1, p2 класса CLine CLine():p1(* new CPoint), p2(* new CPoint) < // . >
Использование класса CLine в другом методе:
// ссылка на объекты как члены-данных класса CLine cl1; // вызывается конструктор, который инициализирует переменные-ссылки p1, p2 // дополнительные переменные CPoint point1, point2; int x, y; // проверка, как конструктор заполнил координаты точек отрезка cl1.GetPoints(&point1, &point2); point1.GetXY(&x, &y); // x = 0; y = 0 point2.GetXY(&x, &y); // x = 1; y = 1 // установить новые значения point1.SetXY(3, 8); // записать точку (3; 8) point2.SetXY(5, 9); // записать точку (5; 9) cl1.SetPoints(&point1, &point2); // проверка CPoint pp1, pp2; cl1.GetPoints(&pp1, &pp2); pp1.GetXY(&x, &y); // x = 3; y = 8 pp2.GetXY(&x, &y); // x = 5; y = 9
Связанные темы
- Объекты класса как члены данных класса. Примеры
- Понятие класса. Объявление класса. Объект класса. Классы в среде CLR. Инкапсуляция данных в классе