Другое > 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/

Вообще и самому пробелы убрать можно, раз уж строку целиком читаешь. Или читать посимвольно, игнорируя пробелы.
Навигация
Главная страница сообщений
Следующая страница
Предыдущая страница

Перейти к полной версии