Во многих проектах возникает необходимость создания иерархии классов для их совместного использования и взаимодействия. ”Лучше класс подогнать под контейнер чем контейнер под класс”. Поведение RTTI(run time type information) включает в себя несколько гибких моментов которые вам могут помочь,но иногда и навредить. Все зависит от ситуации и корректности написания вашего кода. Рассмотрим пример: Допустим у вас есть иерархия классов автомобилей и вам требуется выполнить над ними определенные изменения.
//Типичный базовый класс содержащий виртуальные функции.
class Car {
virtual void see() {}
virtual void setspeed() {}
}
Class Car может быть унаследован от какого нибудь стандартного класса. Например: SaveObj (сохранения объектов). CObject (MFC класс), наследуется базовым для переопределения нужных вам функций (функций записи данных). Производные классы: class Audi: public Car {
public:
short speed;
void see(){};
void setspeed(){};
}
class Bmw : public Car {
};
После этого получается: Container<car>c; // Вам понадобится контейнер с доступом к произвольному элементу.
Audi audi1;
Bmw bmw1
c.push_back(audi1);
c.push_back(bmw1);
.. // добавляем гараж автомобилей.
Как выбрать нужный нам автомобиль? Существует много способов: 1) Вложенным классом. СAuto position; И написанием функции GetPosition() { return &position; } (она должна быть в базовом классе виртуальной). int main() {
CAuto myposition;
for (I = с.begin(); I i!= с.end();i++) {
Car *p = c->GetAt(i);
if (mypositon == p->getPosition){
// код
}
Подобный метод был упомянут в книге Страуструпа:
void check(car *p) {
if (p.typeid() == audi) {
// do something;
}
if (p.typeid() == bmw) {
}
}
Так называемая switch проверка. Лучший вариант ее использования это dynamic_cast<>; (С++ .Специальное издание.Б.Страуструп.) 2) Методом определения объекта могут быть и встроеные функции системы. Например нажатие мышкой для графических объектов: OnLButtonDown(point) { // нажатие левой кнопки мыши point –точка попадания
for() // цикл по контейнеру
Car *p = c->GetAt(I); // I – элемент итерации контейнера,
if (p->GetPosition->PtInRegion(point)) { // если мы попали в позицию где стоит машина.
// код
}
}
3) Определение машины со временем: CTime t;
Car *p;
if (p->GetTime == t.Now()) {
// код
}
4) Может возникнуть ситуация когда один объект должен зависеть от других.
Установить чтобы одна машина двигалась за другой. audi.speed = 100;
bmw.speed = 120;
audi.speed = bmw.getSpeed(); // getSpeed возвращает значения переменной Bmw.speed;
Сейчас audi.speed = 120; Но если мы изменим скорость bmw,
bmw.setSpeed(130);
то audi.speed останется 120. А должно быть 130. Для этого используйте int *speed. И getSpeed() возращает адрес &speed;
audi.speed = getSpeed();
Замечание: При записи указателей в файл и выводе на экран могут возникнуть ошибки. С ними можно бороться при помощи memcpy или внешних/программных библиотек.
Так же для безопасности применяйте smart_ptr (зависит от поведения, например: клиент-сервер)
|