Member
Статус: Не в сети Регистрация: 24.07.2005 Откуда: Moscow
Спецы, подскажите, в инете искал - не нашел:
Есть функция, в нее передается массив. Для корректной работы функции ей необходимо знать кол-во элементов передаваемого массива. sizeof() внутри функции не работает, а больше я не знаю способов определить кол-во элементов.
Можно, конечно, в функцию вручную передать длину массива, но тогда теряется ее универсальность, да и работать с ней будет менее удобно.
Вобщем взял этот пример из книжки..но компилятор зацикливается и прекращает компилирование, выдав 103 ошибки, к=е жутко ругают файл mysql_com.h
Я его взял из комплекта поставки MySQL, так что не думаю что с ним чтото нето. Помогите, плиз, разобраться!
Member
Статус: Не в сети Регистрация: 12.12.2003 Откуда: Уфа
Прошу помощи! Пишу программу, не знаю как лучше организовать данные с позиций ООП. Программа будет отображать графически(3Д и 2Д) и работать с разными типами данных. Один объект в программе может быть поверхностью, другой - набором точек в трехмерном пространстве, третий набором линий. Объектов может быть любое количество. Соответственно мне надо определять классы TSurface, TPoints, TLines, для них реализовать все необходимые методы, в частности метод отображения на экране. Но, поскольку объектов каждого типа может быть произвольное число, мне надо определять 3 контейнера? По одному для каждого типа и, например для отображения всех объектов на экране должен быть такой код:
Код:
vector <TSurface> v_Surface; vector <TPoints> v_Points; vector <TLines> v_Lines; .... for (int i=0; i<v_Surface.size(); i++) //Отображение поверхностей v_Surface[i].Draw; for (int i=0; i<v_Lines.size(); i++) //Отображение наборов линий v_Lines[i].Draw; for (int i=0; i<v_Points.size(); i++) //Отображение наборов точек v_Points[i].Draw;
И так для каждого типа. По-моему не очень рациональная реализация, ведь надо повторять код для каждого типа.. Как это можно сделать лучше?
kexman Для этого есть виртуальные функции. Создаёшь базовый класс с интерфейсом и наследуешь от него свои сюрфейсы и пойнты. А в векторе хранишь указатели на базовый класс, реально указывающие на твои объекты. Например:
Member
Статус: Не в сети Регистрация: 12.12.2003 Откуда: Уфа
Спасибо огромное! Вначале не понял, потом почитал Либерти, разобрался.
Единственное, непонятно про лучше завернуть в класс-обёртку, чтобы не забыть удалить объекты при уничтожении . Это что такое?
Добавлено спустя 3 минуты, 31 секунду Блин, а я и не знал, оказывается ООП и в частности С++ дает такие охренительные возможности, жуть! дух захватывает, наследование - супер!
Единственное, непонятно про лучше завернуть в класс-обёртку, чтобы не забыть удалить объекты при уничтожении . Это что такое?
Ну, дело в том, что при уничтожении вектора, память выделенная под объекты, не освободится, т.к. нужно вручную заделетить каждый указатель. Т.е.:
Код:
vector<Drawable*> objs; ... // создаём объекты objs.push_back( new Surface ); ... // освобождаем память for ( int i = 0; i < objs.size(); ++i ) delete objs[i];
Если этого не сделать, произойдёт утечка памяти (и возможно других ресурсов, если ты их выделяешь в конструкторе своих объектов). Поэтому лучше сделать небольшой класс-обёртку для вектора, который в деструкторе удалит всё автоматически:
Код:
class VectorDrawsPtr { public: VectorDrawsPtr() {} ~VectorDrawsPtr() { for ( int i = 0; i < vec_.size(); ++i ) delete vec_[i]; }
Member
Статус: Не в сети Регистрация: 14.01.2004 Откуда: Киев, Украина
Билли Бонс писал(а):
for ( int i = 0; i < vec_.size(); ++i ) delete vec_[i];
Интересно написал, использовал префиксный инкремент, но он тут бесполезен, ибо используются не итераторы а простой индекс Добавлено спустя 4 минуты, 47 секунд ИМХО лучше нечто такого (правда пока незнаю соберется это или нет ))
Код:
template <class T> class VectorWrapper : public std::vector<T> { public: ~VectorWrapper() { for(typename std::vector<T>::iterator i = begin(); i != end(); ++i) delete *i; } }
Member
Статус: Не в сети Регистрация: 12.12.2003 Откуда: Уфа
Билли Бонс Но твой класс же не будет содержать в себе все методы контейнера vector. Лучше наверное как-нибудь наследовать от класса вектор, чтобы не перегружать потом push_back(), size()... Вроде вариант Daemon как раз под это подходит, только я не знаю еще, как использовать шаблоны.
kexman Обычно всё равно для своей коллекции требуются свои методы, а не вектора (векторные бывают иногда даже нежелательны). Концепции проектирования, пожалуй, в двух словах не расскажешь, это приходит с опытом (при желании изучать их, конечно). Ни разу не встречал на самом деле наследование от стандартных контейнеров.
kexman писал(а):
только я не знаю еще, как использовать шаблоны
Ну, класс VectorWrapper можешь использовать также как vector, разве что для пущей безопасности сделать так:
Код:
template <class T> class VectorWrapper : public std::vector<T> { };
template <class T*> class VectorWrapper : public std::vector<T*> { public: ~VectorWrapper() { for(typename std::vector<T>::iterator i = begin(); i != end(); ++i) delete *i; } };
Member
Статус: Не в сети Регистрация: 14.01.2004 Откуда: Киев, Украина
Ага, частичная специализация с глюком Поправде говоря я особо тоже не натыкаюсь на либы, там где часто испольщуются шаблоны. Кроме STL конечно, а так это МС со своими WTL, ATL любит лепить их куда не попадя
Билли Бонс писал(а):
Ни разу не встречал на самом деле наследование от стандартных контейнеров.
Ага, я тоже, потому что функторы руллят, выше описаное действие лучше через for_each сделать
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения