Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
С++ Страуструп.doc
Скачиваний:
4
Добавлен:
18.04.2019
Размер:
2.72 Mб
Скачать

12.2.4 Отношения принадлежности

Если используется отношение принадлежности, то существует два основных

способа представления объекта класса X:

[1] Описать член типа X.

[2] Описать член типа X* или X&.

Если значение указателя не будет меняться и вопросы

эффективности не волнуют, эти способы эквивалентны:

class X {

//...

public:

X(int);

//...

};

class C {

X a;

X* p;

public:

C(int i, int j) : a(i), p(new X(j)) { }

~C() { delete p; }

};

В таких ситуациях предпочтительнее непосредственное членство объекта,

как X::a в примере выше, потому что оно дает экономию

времени, памяти и количества вводимых символов. Обратитесь также

к $$12.4 и $$13.9.

Способ, использующий указатель, следует применять в тех

случаях, когда приходится перестраивать указатель на

"объект-элемент" в течении жизни "объекта-владельца". Например:

class C2 {

X* p;

public:

C(int i) : p(new X(i)) { }

~C() { delete p; }

X* change(X* q)

{

X* t = p;

p = q;

return t;

}

};

Член типа указатель может также использоваться, чтобы дать возможность

передавать "объект-элемент" в качестве параметра:

class C3 {

X* p;

public:

C(X* q) : p(q) { }

// ...

}

Разрешая объектам содержать указатели на другие объекты, мы создаем

то, что обычно называется "иерархия объектов". Это альтернативный

и вспомогательный способ структурирования по отношению к иерархии

классов. Как было показано на примере аварийного движущегося

средства в $$12.2.2, часто это довольно тонкий вопрос проектирования:

представлять ли свойство класса как еще один базовый класс

или как член класса. Потребность в переопределении следует считать

указанием, что первый вариант лучше. Но если надо иметь

возможность представлять некоторое свойство с помощью различных

типов, то лучше остановиться на втором варианте. Например:

class XX : public X { /*...*/ };

class XXX : public X { /*...*/ };

void f()

{

C3* p1 = new C3(new X); // C3 "содержит" X

C3* p2 = new C3(new XX); // C3 "содержит" XX

C3* p3 = new C3(new XXX); // C3 "содержит" XXX

//...

}

Приведенные определения нельзя смоделировать ни с помощью производного

класса C3 от X, ни с помощью C3, имеющего член типа X, поскольку

необходимо указывать точный тип члена. Это важно для классов с

виртуальными функциями, таких, например,как класс Shape ($$1.1.2.5), и

для класса абстрактного множества ($$13.3).

Заметим, что ссылки можно применять для упрощения классов,

использующих члены-указатели, если в течение жизни объекта-владельца

ссылка настроена только на один объект, например:

class C4 {

X& r;

public:

C(X& q) : r(q) { }

// ...

};

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]