| Другое > Hard'n'Soft |
| Програмирование на C++ |
| << < (15/25) > >> |
| HoRRoR:
--- Цитата ---Класс у меня просто Stack ведь называется, зачем тогда придумали дописывать ещё и <T>? Я ведь и так предыдущей строчкой обязан напомнить о шаблоне так зачем же дважды это делать? --- Конец цитаты --- Потому что тебе никто не запрещает написать какой угодно другой шаблон для этой функции класса: --- Код: ---template <> bool Stack<int>::push(const int &pushValue) { cout << "Stack::push() for int called!" << endl; ... } template <typename T> bool Stack<T>::push(const T &pushValue) { cout << "Stack::push() for another type called!" << endl; ... } --- Конец кода --- А T писать - потому что класса Stack не существует, существует класс Stack<тип> для каждого из типов, с которыми используется шаблон Stack. |
| gepar:
А почему нельзя так --- Код: ---double printArray( const T *array, int count, int low=0, int high=count ) --- Конец кода --- Count у меня здесь количество элементов в массиве, low - первый элемент который нужно печатать, high - последний элемент который нужно печатать. И как в таком случае тогда поступать? Здесь я хочу чтобы на печать отправлялся полностью массив если функции передано два аргумента, и не полностью если 3 или 4 аргумента. Добавлено позже: Нет, я конечно могу сделать так чтобы вместо count сразу был high --- Код: ---double printArray( const T *array, int high, int low=0) --- Конец кода --- И это в данном случае подойдёт но мне на будущее, так сказать, хотелось бы знать что делать когда я хочу необязательному аргументу функции присвоить значение обязательного аргумента вот как здесь я писал. |
| HoRRoR:
--- Цитата ---А почему нельзя так --- Конец цитаты --- Потому что спецификация этого не позволяет. --- Цитата ---И как в таком случае тогда поступать? --- Конец цитаты --- Как вариант: --- Код: ---double printArray( const T *array, int count, int low=0, int high=-1) { if(high == -1) high = count; ... } --- Конец кода --- |
| gepar:
Переделываю старую программу которая была что-то вроде искуственного массива, так вот там раньше была перегрузка в классе объявлена вот так в .h файле: --- Код: ---const Array &operator=( const Array & ); // assignment operator --- Конец кода --- и вот так потом в cpp файле --- Код: ---const Array &Array::operator=( const Array &right ) --- Конец кода --- Когда я создал свой шаблон с этим классом для template <typename T> то я теперь не знаю как в cpp файле указать что функция пренадлежит шаблону, я уже и так и эдак, а оно всё равно ошибки сыплет. Добавлено позже: Уже разобрался, тип же тоже меняется так что надо было писать --- Код: ---template <typename T> const Array<T> &Array<T>::operator=( const Array &right ) --- Конец кода --- Добавлено позже: И всё равно не смог я всё подружить с шаблоном, перегрузка операций ввода и вывода у меня говорят что объявляю я их криво , посмотрите пожалуйста. P.S main находится в Array.cpp. |
| HoRRoR:
Нельзя шаблонные функции описывать в cpp. Там будут присутствовать только те шаблонные типы, которые использовались. Т.е. если ты используешь Array<int> в .cpp, то он будет там присутствовать, иначе - нет. Так что всё описывай в .h. |
| gepar:
Ну я пробовал перенести перегрузку ввода и вывода в .h файл, но это не помогло, сейчас попробую всё перенести туда. Ну и маленькая программка для разминки из примера преподши (я добавил только вывод в каждой функции чтобы было видно что запускается) --- Код: ---#include<iostream> using std::cout; //Перегрузка abs() тремя способами int abs(int n); long abs(long n); double abs(double n); int main() { cout<<"Absolute -10: "<<abs(-10)<<'\n'; cout<<"Absolute -10L: "<<abs(-10L)<<"\n"; cout<<"Absolute-10.01: "<<abs(-10.01)<< "\n"; return 0; } //abs() для целых int abs(int n) { cout<<"NORMAL!!!!!";return n<0?-n:n; } // abs() для длинных целых long abs(long n) { cout<<"LONG!!!!!";return n<0?-n:n; } // abs() для вещественных двойной точности double abs(double n) {cout<<"DOUBLE!!!!!";return n<0?-n:n; } --- Конец кода --- Собственно как это вообще работает? o_0 Судя по выводу (и по тому что для функцию int abs(int n) можно удалить) для int эта функция abs не используется вообще. Дальше каким это образом компилятор принимает -10L как аргумент функции, там же после цифры буква. Ну и почему идёт странный вывод в итоге: печатается сначала то что на вывод в потоке в функции я отправил, а потом уже что отправлено в поток в main o_0 Ведь по идеи должно печатать сначала Absolute -10L: из main'а, потом то что в функции на вывод отправлено LONG!!!!!, а потом уже число после обработки которое возвращает функция так почему же всё происходит совсем не так? |
| HoRRoR:
Ты основы вообще изучал? В частности - порядок вычисления выражения. Сначала вычисляется функция (в ней срабатывает вывод), а уже затем только вывод в main с результатом вычисления функции. А буквы в конце констант вообще стыдно не знать. L - long, U - unsigned, F - float. 10ULL - unsigned long long, к примеру. А с интом не работает, видимо, потому, что где-то эта функция уже определена. Если ты опишешь тело функции до main - то будет вызываться именно та, которая нужна. |
| gepar:
--- Цитата: HoRRoR ---Ты основы вообще изучал? В частности - порядок вычисления выражения. Сначала вычисляется функция (в ней срабатывает вывод), а уже затем только вывод в main с результатом вычисления функции.А буквы в конце констант вообще стыдно не знать. L - long, U - unsigned, F - float. 10ULL - unsigned long long, к примеру. --- Конец цитаты --- Ну я первый раз увидел чтобы вот так можно было дописать после цифры буквы в конце и компилятор это понял. Добавлено позже: А вот запихнуть всё в .h файл по отношению к шаблонам тоже не получилось, ну точнее в итоге я всё равно дохожу до ошибки как не извращаюсь... Array.cpp||undefined reference to `operator<<(std::ostream&, Array<int> const&)'| Посмотри пожалуйста. |
| HoRRoR:
Проблема в том, что у тебя этот оператор внутри класса описан не как шаблонная функция. 1. Опиши функции операторов выше, чем класс. 2. Для этого оставь выше этих функций упоминание о классе - template <typename T> class Array; 3. Измени описание friend'ов с учётом шаблона: --- Код: --- friend ostream &operator<< <T>( ostream &, const Array<T> & ); friend istream &operator>> <T>( istream &, Array<T> & ); --- Конец кода --- |
| gepar:
--- Цитата: HoRRoR ---Проблема в том, что у тебя этот оператор внутри класса описан не как шаблонная функция. --- Конец цитаты --- Ну это я с самого начала заметил в виде предупреждений компилятора, но не знал как исправить это. Так работает, спасибо за помощь. Но тут ещё хотелось бы хоть косвенно понять почему так . Вот зачем было дописывать вот так например --- Код: --- friend ostream &operator<< <T>( ostream &, const Array<T> & ); --- Конец кода --- в итоге получается при вызове --- Код: --- friend ostream &operator<< int ( ostream &, const Array<int> & ); --- Конец кода --- что непонятно как работает (зачем int перед аргументами?) Ну и почему надо было дружественные функции писать перед тем как их использовать (я же попробовал специально оставить их в конце - фигушки, так не получается).Ну хотя бы в двух словах. |
| HoRRoR:
Это каким чудом у тебя <int> превращается в int? Ты же не писал "operator << T (...". int в классе подставится вместо T таким образом: --- Код: --- friend ostream &operator<< <int>( ostream &, const Array<int> & ); --- Конец кода --- В самой функции это будет так: --- Код: ---ostream &operator<<( ostream &output, const Array<int> &a ) --- Конец кода --- Т.е. <int> по сути означает "typename T = int". Это как аргумент функции, только аргумент шаблона. Проводя аналогию: --- Код: ---void foo(int a); ... foo(10); template <typename T> void foo(T a); ... foo<int>(10); --- Конец кода --- Вот <int> - это передача аргумента шаблона. |
| gepar:
Я тут создаю свой класс вектор и в итоге получаю вот такое: --- Код: ---C:\c++\Projects\Vector\Vector.cpp|137|error: cannot declare member function `static int Vector::getCount()' to have static linkage| --- Конец кода --- Собственно в первый раз с такой ошибкой встречаюсь,в чём может быть проблема? В классе Vector в private есть --- Код: ---static int count;// колличество созданных классов --- Конец кода --- Ну а функция по возврату этого значения выглядит как --- Код: ---static int Vector::getCount() { return count; } --- Конец кода --- Так в чём же тогда может быть проблема? Добавлено позже: Тьфу, static же в cpp файле не надо было писать уже, я и забыл. Добавлено позже: Почему при делении на число получается 1.#INF в выводе, когда я допустил ошибку (вместо равно в проверке условия написал присваивание)? Программа ведь должна была вылететь с кодом ошибки 100 Собственно .h файл --- Код: ---# ifndef VECTOR_H # define VECTOR_H #include <iostream> using std::ostream; using std::istream; class Vector { friend ostream &operator<<(ostream&,const Vector&); public: Vector(); Vector(const Vector&); ... void operator/ (double); static int getCount(); private: int size; //количество элементов int now;// состояние double *vect;//сам вектор static int count;// количество созданных классов }; #endif --- Конец кода --- И функция деления: --- Код: ---void Vector::operator/ (double p) { if (p=0) exit(100); if (size==1) *vect/=p; else for (int i=0;i<size;i++) vect[i]=(double)vect[i]/p; } --- Конец кода --- Почему работа продолжается при такой ошибке, я ведь явно указал выход с ошибкой 100 и никаких или. |
| HoRRoR:
--- Цитата --- if (p=0) exit(100); --- Конец цитаты --- Сам вдумайся в то, что ты написал. Во-первых, это присваивание. Во-вторых, оно всегда будет давать false. В-третьих, даже при ненулевых значениях возможно получить INF - если число будет слишком маленьким, чтобы результат деления поместился. В-четвёртых, возьми за правило писать double как 0.0, float как 0.0f. |
| gepar:
--- Цитата: HoRRoR ---Во-первых, это присваивание. --- Конец цитаты --- А я то и не заметил :). Я нашёл эту ошибку о чём и написал, но мне стало потом интересно почему же программа не вылетала каждый раз с кодом ошибки 100. HoRRoR,тоесть оно присвоит p значение 0, но тем не менее будет идти как false? Но в таком случае оно дальше бы должно делить на 0 и вылететь всё равно с ошибкой. |
| HoRRoR:
Деление числа с плавающей запятой на ноль - не ошибка и даёт infinitiy. Добавлено позже: --- Цитата ---тоесть оно присвоит p значение 0, но тем не менее будет идти как false? --- Конец цитаты --- Выражение присваивания возвращает результат присваивания. Т.е. (a = 1) == 1 - true. И тут так же, только с нулём, а ноль - это false. |
| gepar:
HoRRoR,ага, вот так оно расценило моё условие, теперь понятно. --- Цитата: HoRRoR ---Деление числа с плавающей запятой на ноль - не ошибка и даёт infinitiy. --- Конец цитаты --- Я думал деление на 0 хоть int, хоть double будет приводить к ошибке при выполнении, а оно во как. Спасибо, буду знать. |
| gepar:
Читаю о манипуляторах потоков и тут тоже возникли некоторые вопросы. Есть ли разница между --- Код: ---# include <iostream> using namespace std; int main() { char *abc="word"; cout<<abc<<'\n'; cout<<static_cast<void*> (abc); // и cout<<(void*) abc; } --- Конец кода --- |
| HoRRoR:
Разница только в операторах приведения типа, поток тут можно и не затрагивать. |
| gepar:
А как бы его избавиться от пробелов в этом случае --- Код: --- char abc[80]; cin.getline(abc,80,EOF); --- Конец кода --- ? Вычитал что есть некаю skipws, но что-то никак не придумаю как бы её подпихнуть во входной поток. |
| HoRRoR:
http://www.cplusplus.com/reference/iostream/manipulators/skipws/ Вообще и самому пробелы убрать можно, раз уж строку целиком читаешь. Или читать посимвольно, игнорируя пробелы. |
| Навигация |
| Главная страница сообщений |
| Следующая страница |
| Предыдущая страница |