Предположим, у меня есть класс шаблона ComplexNumber
, который выглядит так:
template<typename T>
class ComplexNumber {
public:
ComplexNumber() : A(), B() {}
ComplexNumber(const T& r, const T& i) : A(r), B(i) {}
~ComplexNumber(){}
void setA(T A1);
void SetB(T B1);
T getA() const {return A;};
T getB()const {return B;};
ComplexNumber<T> operator+(const ComplexNumber<T> &C){
return ComplexNumber<T>( A + C.getA(), B + C.getB());
}
ComplexNumber<T> operator -(const ComplexNumber<T> &C) {
return ComplexNumber<T>(A - C.getA(), B - C.getB());
};
friend ostream & operator << (ostream &out, const ComplexNumber<T> &c)
{
out << c.A;
out << "+i" << c.B << endl;
return out;
}
private:
T A;
T B;
};
И main()
, который создает эти комплексные числа и сохраняет их в std::vector
:
ComplexNumber<int> complex1(10, 3);
ComplexNumber<int> complex2(2, 56);
ComplexNumber<int> complex3(3, 55);
vector<ComplexNumber<int>> testVector;
testVector.push_back(complex1);
testVector.push_back(complex2);
testVector.push_back(complex3);
Если я хочу отсортировать testVector
от высшего к низшему, сравнивая действительные части, а затем сравнивая мнимые, если действительные части равны, как мне это сделать?
Я не могу использовать стандартную функцию std::sort()
. Я хотел бы сделать это, используя метод или функтор.
Обновлено: Попытка добавить его в функцию:
//This method is outside the scope of the ComplexNumber class
auto compare_by_magnitude = [](const auto& a, const auto& b) {
return a.A*a.A + a.B*a.B < b.A*b.A + b.B*b.B;
};
void sortComplex(vector<ComplexNumber<int>> &c){
std::sort(c.begin(),c.end(),compare_by_magnitude);
}
Мои сообщения об ошибках:
FAILED: complexNumber.exe
cmd.exe /C "cd . && C:\PROGRA~1\JETBRA~1\CLION2~1.3\bin\mingw\bin\G__~1.EXE -g CMakeFiles/complexNumber.dir/main.cpp.obj CMakeFiles/complexNumber.dir/ComplexNumber.cpp.obj -o complexNumber.exe -Wl,--out-implib,libcomplexNumber.dll.a -Wl,--major-image-version,0,--minor-image-version,0 -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 && cd ."
C:\Program Files\JetBrains\CLion 2021.3.3\bin\mingw\bin/ld.exe: CMakeFiles/complexNumber.dir/ComplexNumber.cpp.obj: in function `ComplexNumber<int>::~ComplexNumber()':
C:/PROGRA~1/JETBRA~1/CLION2~1.3/bin/mingw/lib/gcc/x86_64-w64-mingw32/11.2.0/include/c++/bits/stl_heap.h:223: multiple definition of `sortComplex(std::vector<ComplexNumber<int>, std::allocator<ComplexNumber<int> > >&)'; CMakeFiles/complexNumber.dir/main.cpp.obj:C:/Users/elira/Desktop/complexNumber/complexNumber/ComplexNumber.h:51: first defined here
C:\Program Files\JetBrains\CLion 2021.3.3\bin\mingw\bin/ld.exe: CMakeFiles/complexNumber.dir/ComplexNumber.cpp.obj:C:/Users/elira/Desktop/complexNumber/complexNumber/ComplexNumber.h:48: multiple definition of `compare_by_magnitude'; CMakeFiles/complexNumber.dir/main.cpp.obj:C:/Users/elira/Desktop/complexNumber/complexNumber/ComplexNumber.h:48: first defined here
collect2.exe: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
Кстати, есть std::complex
, который вы можете использовать
Ну, для начала вы должны определить сравнение. Как вы хотите, чтобы они были отсортированы? По абсолютной величине? По фазовому углу? Сначала по реальному значению, потом по мнимому?
@ 463035818_is_not_a_number - извините, я должен был это указать. Я хотел бы отсортировать их от высшего к низшему, сравнивая действительные части, а затем сравнивая мнимые, если действительные части равны.
@ Homer512 - извините, я должен был это сказать. Я хотел бы отсортировать их от высшего к низшему, сравнивая действительные части, а затем сравнивая мнимые, если действительные части равны.
Хорошо, тогда второй вопрос: вы сказали, что не можете использовать стандартную сортировку. Означает ли это, что вы не могли понять, как его использовать, или что вам не разрешено его использовать, например. в задании?
Кстати, нет классов шаблонов. ComplexNumber
— это шаблон класса. И в векторе у вас есть ComplexNumber<int>
, который является типом, похожим на другие типы.
@ Homer512 Я не мог понять, как его использовать. Я продолжал получать ошибки с итераторами.
вы должны создать минимальный воспроизводимый пример, чтобы включить его вместе с ошибками компилятора в вопрос.
Ваше сообщение об ошибке не имеет ничего общего с сортировкой. Это ошибка множественного определения. stackoverflow.com/questions/41539456/… Я думаю, он у вас есть в заголовке, хотя должен быть в файле .cpp. Или объявить t встроенным
Если вы хотите сохранить определение sortComplex
в заголовке, вам нужно сделать его inline
; в противном случае вы нарушите ODR, если включите заголовок более чем в одну единицу перевода. переменная лямбда должна быть сделана static
или inline
по той же причине.
Отвечает ли это на ваш вопрос? "множественная ошибка определения, включая заголовочный файл С++ со встроенным кодом из нескольких источников", "Как использовать extern для обмена переменными между исходными файлами?", "Сортировка комплексных чисел в векторе С++"
Чтобы работать с std::sort()
, ваш класс должен быть определен как минимум operator<
:
bool operator< (const ComplexNumber<T>& other) const {
return A < other.A || (A == other.A && B < other.B);
}
Также рекомендуется определять operator==
, но std::sort()
будет работать только с operator<
.
Когда я делаю вышеупомянутое дополнение к вашему классу, этот main()
сортируется по реальному, а затем по мнимому в порядке возрастания:
int main() {
vector<ComplexNumber<float>> vc = { {4, 5}, {1, 3}, {4, 2} };
copy(vc.begin(), vc.end(), ostream_iterator<ComplexNumber<float>>(cout, " "));
cout << endl;
sort(vc.begin(), vc.end());
copy(vc.begin(), vc.end(), ostream_iterator<ComplexNumber<float>>(cout, " "));
cout << endl;
}
Но вы упомянули, что хотите отсортировать в порядке нисходящий. Неправильно определять operator<
в обратном смысле внутри класса, как вы можете себе представить, поэтому вместо этого вы можете передать функцию сравнения в std::sort()
, которая меняет смысл сравнения:
sort(vc.begin(), vc.end(),
[](const ComplexNumber<float> &f1, const ComplexNumber<float> &f2)
{ return ! (f1 < f2); }
);
Помимо этих проблем с компиляцией и семантикой, когда я смотрю на ошибки, которые вы публикуете, я вижу ошибку связь, и кажется, что ваш класс определяется несколько раз. Это говорит о том, что во включаемом файле, который определяет ваш класс, отсутствует защита включения.
std::sort()
по умолчанию сортирует в порядке возрастания (от низкого к высокому), но вместо этого OP хочет сортировать в порядке убывания (от высокого к низкому). Поэтому вам нужно использовать предикат в 3-м параметре std::sort()
, чтобы справиться с этим. Например, реализуйте operator>
в классе, а затем используйте std::greater
для предиката.
@RemyLebeau спасибо за улов! Я обновил свой ответ, чтобы показать, как использовать лямбда для функции сравнения. std::greater
будет работать, но требует, чтобы OP определил operator>
.
Большое спасибо за помощь, Дерек. Вы не представляете, как я это оценил. Я новичок в кодировании, так что это спасло мне жизнь, пытаясь завершить этот проект. Все работало отлично, как вы и сказали. Еще раз спасибо. Хотел бы я проголосовать за тебя миллион раз
@DerekT.Jones, еще один вариант, если класс имеет только operator<
определенный, без использования предиката, вы можете sort()
vector
вместо этого использовать обратные итераторы, например: sort(vc.rbegin(), vc.rend());
Используя operator<
, sort()
поместит более низкие значения в сторону начального итератора, что в данном случае будет ближе к концу вектора, а не к его фронту.
нет очевидного способа сравнить два комплексных числа с помощью
<
. Вам нужно определить, как вы хотите их отсортировать. Например, по величине или по углу