Шаблоны классов [дубликат]

92
06 февраля 2021, 21:20
На этот вопрос уже даны ответы здесь:
Ссылка на неразрешенный внешний элемент (2 ответа)
Перегрузка шаблонных операторов с разделением на описание и имплементацию (1 ответ)
Перегрузка операторов >> и << в шаблонном классе как дружественных функций (3 ответа)
Закрыт 1 год назад.

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

1>Source.obj : error LNK2019: unresolved external symbol "bool __cdecl operator==(class set,class set)" (??8@YA_NV?$set@VThor@@@@0@Z) referenced in function "void __cdecl menu(void)" (?menu@@YAXXZ)

не работатет 10й кейс в меню

вот программа

set.h

#include <iostream>
using namespace std;
//Объявление класса "Множество":
template <class T>
class set {
private:
    T *ptr;
    int max_size;
    int count;
public:
    //Конструкторы:
    set(int maxim);
    set(const set &x);
    //Деструктор:
    ~set();
    void add(T x);              //добавление эл-та в множество
    void del(T x);              //удаление эл-та из множества
    bool check_in(T x);         //проверка вхождения эл-та в множество
    void output();              //Вывод множества на экран
    void find(double f) {       //Поиск длины окружности
        bool flag = true;
        for (int i = 1; i <= count; i++) {
            if (abs((ptr[i].getVol() - f) / ptr[i].getVol()) < 0.00001) {
                cout << "\t" << ptr[i] << "\n";
                flag = false;
            }
        }
        if (flag)
            cout << "\nНичего не найдено";
    }
    set operator=(const set&);  //перегрузка: операции присваивания
    set operator*(const set&);  //перегрузка: пересечение двух множеств
    set operator+(const set&);  //перегрузка: объединение двух множеств
    set operator-(const set&);  //перегрузка: разность двух множеств
    friend bool operator== (set <T> s1, set <T> s2);//операция: сравнение двух множеств
};
template <class T>
void set<T> ::add(T x)//удаление
{
    if (count < max_size)
    {
        if (!check_in(x))
        {
            count += 1;
            ptr[count] = x;
            cout << "Добавление прошло успешно";
        }
        else
            cout << "Добавление невозможно (Такой э-т уже есть в множестве)";
    }
    else
        cout << "Добавление невозможно (Множество полно)";
}

template <class T>
void set <T>::del(T x)//удаление
{
    bool ok;
    ok = false;
    if (count != 0)
    {
        for (int i = 1; i <= count; i++)
        {
            if (ptr[i] == x)
            {
                for (int j = i; j <= count; j++)
                {
                    ptr[j] = ptr[j++];
                }
                count -= 1;
                ok = true;
            }
        }
        if (ok)
            cout << "Удаление прошло успешно";
    }
    else
        cout << "Удаление невозможно";
}

template <class T>
bool set <T>::check_in(T x)
{
    for (int i = 1; i <= count; i++)
        if (ptr[i] == x)
            return true;
    return false;
}

template <class T>
void set<T>::output()
{
    if (count == 0)
    {
        cout << "{}";
        return;
    }
    cout << "{";
    if (count > 1) {
        cout << ptr[1];
        for (int i = 2; i <= count; i++)
            cout << ", " << ptr[i];
    }
    else {
        for (int i = 1; i <= count; i++)
            cout << ptr[i];
    }
    cout << "}";
}

template <class T>
set<T> set<T>::operator*(const set<T>& s2)//пересечение
{
    set <T> s3(max_size * 2);
    s3.count = 0;
    for (int i = 1; i <= count; i++)
        for (int j = 1; j <= s2.count; j++) {
            if (s2.ptr[j] == ptr[i])
            {
                s3.count += 1;
                s3.ptr[s3.count] = ptr[i];
            }
        }
    return s3;
}

template <class T>
set<T> set<T>::operator+(const set<T>& s2) //объединение множеств
{
    bool in;
    set <T> s3(max_size * 2);
    s3.count = 0;
    for (int i = 1; i <= count; i++)
    {
        s3.count += 1;
        s3.ptr[s3.count] = ptr[i];
    }
    for (int i = 1; i <= s2.count; i++)
    {
        in = s3.check_in(s2.ptr[i]);
        if (!in)
        {
            s3.count += 1;
            s3.ptr[s3.count] = s2.ptr[i];
        }
    }
    return s3;
}
template <class T>
//разность
set<T> set<T>::operator-(const set<T>& s2)
{
    set <T> s3(max_size);
    s3.count = 0;
    bool flag;
    for (int i = 1; i <= count; i++) {
        flag = true;
        for (int j = 1; j <= s2.count; j++) {
            if (ptr[i] == s2.ptr[j]) {
                flag = false;
            }
        }
        if (flag) {
            s3.count += 1;
            s3.ptr[s3.count] = ptr[i];
        }
    }
    return s3;
}
template<class T> // отв за создание 4го элемента
set<T> set<T>::operator=(const set<T>& s) {
    if (&s == this)     //сравнение адресов (проверка на присваивание сам себя)
        return *this;
    if (ptr) delete[] ptr;
    max_size = s.max_size;
    if (s.ptr) {
        ptr = new T[max_size + 1];
        for (int i = 1; i <= max_size; i++) {
            ptr[i] = s.ptr[i];
        }
    }
    count = s.count;
    return *this;
}
template <typename M>
bool operator==(const set <M> s1, const set <M> s2)
{
    bool ok;
    if (s1.count != s2.count)
        return false;
    for (int i = 1; i <= s1.count; i++) {
        ok = false;
        for (int j = 1; j <= s2.count; j++) {
            if (ptr[i] == ptr[j])
                ok = true;
            break;
        }
        if (ok == false)
            return false;
    }
    return true;
}

template <class T>
set<T>::set(int maxim)
{
    ptr = new T[maxim + 1];
    T p;
    max_size = maxim;
    count = 0;
}

template <class T>
set<T>::set(const set &x)//заполнение массива значениями
{
    max_size = x.max_size;
    count = x.count;
    ptr = new T[max_size + 1];
    for (int i = 1; i <= max_size; i++)
        ptr[i] = x.ptr[i];
}

template <class T>
set<T>::~set()
{
    delete[]ptr;
}

thor.h

#include <iostream>
#include <math.h>
using namespace std;
class Thor {
    double R, r, h;
public:
    Thor(double = .0, double = .0, double = .0);                    // конструктор с умолчанием
    void setValue(double, double, double);                  // установка данных
    double getr() { return r; }                                // получение внутрннего радиуса
    double getR() { return R; }                                // получение внешнего радиуса
    double getH() { return h; };
    double getVol() { return (3.14159265*3.14159265 * 2 * (r - h)*(R - r - 2 * h)*(R - r - 2 * h)); }          //объем тора V=π2*2r*(R-r)2 
    friend istream& operator >> (istream & stream, Thor &ob);
    friend ostream& operator<<(ostream & stream, Thor &ob);
    friend bool operator==(Thor &, Thor &);
    Thor& operator=(const Thor& ob)                              //перегрузка =
    {
        if (this == &ob)                                        //проверяем на присвоения к себе
            return *this;
        r = ob.r;
        R = ob.R;
        h = ob.h;
        return *this;
    }
};
bool operator==(Thor &a, Thor &b)
{
    return (a.r == b.r && a.R == b.R && a.h == b.h);
}
//Функции-элемента класса Thor
Thor::Thor(double a, double b, double c) {
    setValue(a, b, c);
}
void Thor::setValue(double RR, double rr, double HH) {
    R = RR;
    r = rr;
    h = HH;
}
//дружественная функция – перегруженная операция вставки в поток 
ostream& operator<<(ostream & stream, Thor &ob) {
    stream << " R= " << ob.R << " r= " << ob.r << " толщина тора = " << ob.getH() << " объем тора =" << ob.getVol() << "" << endl;
    return stream;
}
//дружественная функция – перегруженная операция извлечения из потока
istream& operator >> (istream & stream, Thor &ob) {
    stream >> ob.R >> ob.r >> ob.h;
    return stream;
}

main.cpp

   #include <iostream>
#include "conio.h"
#include <math.h>
#include <string.h>
#include "thor.h"
#include "set.h"
using namespace std;
void menu() {
    int n;
    char choose;
    bool flag = true;
    int max = 3;
    set <Thor> set1(max);
    set <Thor> set2(max);
    set <Thor> set3(max * 2);
    Thor x;
    do {
        cout << '\n'
            << "\n\n Меню работы над множествами "
            << "\n1. Добавление элемента"
            << "\n2. Удаление элемента"
            << "\n3. Проверка на наличие"
            << "\n4. Присвоение одного множества другому"
            << "\n5. Пересечение"
            << "\n6. Объединение"
            << "\n7. Разность"
            << "\n8. Вывод на экран"
            << "\n9. Поиск по объему (только для типа Thor)"
            << "\n10. Проверка равенства сетов"
            << "\n0. Выход"
            << "\n\nВведите : ";
        cin >> n;
        switch (n)
        {
        case 1:cout << "Выберете множество для добавления (1 или 2) : ";
            cin >> choose;
            cout << "Введите э-т : ";
            cin >> x;
            if (choose == '1')
                set1.add(x);
            if (choose == '2')
                set2.add(x);
            break;
        case 2:cout << "Выберете множество для удаления (1 или 2) : ";
            cin >> choose;
            cout << "Введите величину элемента : ";
            cin >> x;
            if (choose == '1')
                set1.del(x);
            if (choose == '2')
                set2.del(x);
            break;
        case 3:cout << "Выберете множество для проверки(1 или 2) : ";
            cin >> choose;
            cout << "Введите величину элемента : ";
            cin >> x;
            if (choose == '1')
            {
                if (set1.check_in(x))
                    cout << "Элемент содержится в данном множестве";
                else
                    cout << "Элемент не содержится в данном множестве";
            }
            if (choose == '2')
            {
                if (set2.check_in(x))
                    cout << "Элемент содержится в данном множестве";
                else
                    cout << "Элемент не содержится в данном множестве";
            }
            break;
        case 4:cout << "Выберете в какое множество копировать (1 или 2) : ";
            cin >> choose;
            if (choose == '1')
                set1 = set2;
            if (choose == '2')
                set2 = set1;
            break;
        case 5:set3 = set1*set2;
            cout << "Результат записан в 3е множество";
            break;
        case 6:set3 = set1 + set2;
            cout << "Результат записан в 3е множество";
            break;
        case 7:cout << "Выберете вычитаемое (1 - из второго первое /2 - из первого второе) : ";
            cin >> choose;
            if (choose == '1')
                set3 = set1 - set2;
            if (choose == '2')
                set3 = set2 - set1;
            cout << "Результат записан в 3е множество";
            break;
        case 8:cout << "Выберите множество для вывода (1 или 2 или 3) : ";
            cin >> choose;
            if (choose == '1')
                set1.output();
            if (choose == '2')
                set2.output();
            if (choose == '3')
                set3.output();
            break;
        case 9:double f;
            cout << "Введите объем : ";
            cin >> f;
            cout << "Выберите множество для поиска(1 или 2 или 3) : ";
            cin >> choose;
            if (choose == '1')
                set1.find(f);
            if (choose == '2')
                set2.find(f);
            if (choose == '3')
                set3.find(f);
            break;

        case 10:cout << "Проверка равентсва сетов"; //////////////////////////////////////////
            if (set1 == set2)
                cout << "Равны" << endl;
            else
                cout << "Не равны" << endl;
            break;

        case 0:return;
        default:cout << "Действие не выбрано";
        }
    } while (true);
}
int main()
{
    setlocale(LC_CTYPE, "Russian");
    menu();
}
Answer 1
template <class T>
class set {
private:
    //...
    template <class M>
    friend bool operator== (const set <M> s1, const set <M> s2);
};
READ ALSO
Сортировка слов по алфавиту

Сортировка слов по алфавиту

Задача такова, что в обычном тексте на русском языке, который находится в файлеtxt выделить оттуда кусок текста, выбрать из него слова и отсортировать...

112
C, откуда 3 байта?

C, откуда 3 байта?

Вот простенький код, на экран выводит число равное 3, почему? откуда взялись эти 3 байта

92
Изменение размера окна с помощью мышки

Изменение размера окна с помощью мышки

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

142
не могу получить значение ячейки в QTableWidget

не могу получить значение ячейки в QTableWidget

имеется таблица,необходимо было сделать ввод в ячейки только double:

128