Форум программистов, компьютерный форум CyberForum.ru

Простенький класс работы с комплексными числами. - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 13, средняя оценка - 5.00
Slimmy
 Аватар для Slimmy
65 / 18 / 2
Регистрация: 09.10.2010
Сообщений: 97
29.09.2011, 22:17     Простенький класс работы с комплексными числами. #1
Добрый вечер, уважаемые!
На днях решил вспомнить то, чему учили в университете и понял, что много чего забыл. Попробовал написать класс работы с комплексными числами. Вот что получилось. Скорее всего получилось очень и очень коряво. Вот именно за этим к Вам, уважаемые, и обращаюсь. Вопросы - внизу.

Драйвер класса.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include "stdafx.h"
#include "complex.h"
#include <iostream>
#include <iomanip>
using namespace std;
 
int main(){
    complex * number, sum, diff; // Указатель на класс, объект "сумма", объект "разность".
    float real, im; // Вспомогательные переменные.
    unsigned short int size, num1, num2; // Размер массива объектов, номера "активных" чисел.
    
    cout << setw(20) <<"***Driver for complex class***" << endl;
    do{
        cout << "Input the qt. of elements: ";
        cin >> size;
    }
    while(size < 2);
    
    number = new complex[size];
    if(number == NULL){
        cout << "Sorry! Memory not captured!" << endl;
        system("pause");
        return 1;
    }
    
    for(int i = 0; i < size; i++){
        cout << "Input the real part of the number: ";
        cin >> real;
        cout << "Input the imaginary part of the number: ";
        cin >> im;;
        number[i].initNumber(real, im);
    }
 
    cout << "All numbers in array." << endl;
    for(int i = 0; i < size; i++){
        cout << i << ") ";
        number[i].printNumber();
    }
 
    do{
        cout << "Input two number for adding/minusing: ";
        cin >> num1 >> num2;
    }
    while(num1 < 0 || num1 > size || num2 < 0 || num2 > size);
    
    sum.initNumber((number[num1].getReal() + number[num2].getReal()), (number[num1].getImaginary() + number[num2].getImaginary()));
    cout << "Summ of " << num1 << " and " << num2 << ": ";
    sum.printNumber();
 
    cout << "Difference " << num1 << " and " << num2 << ": ";
    diff.initNumber((number[num1].getReal() - number[num2].getReal()), (number[num1].getImaginary() - number[num2].getImaginary()));
    diff.printNumber();
    
    system("pause");
    delete[]number;
    return 0;
}
Прототип класса.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#ifndef COMPLEX_H
#define COMPLEX_H
#ifndef IOSTREAM
#define IOSTREAM
#endif
#ifndef STDAFX_H
#define STDAFX_H
#endif
 
class complex{
    public:
        float addReal (float re1, float re2); // Сложение действительной части числа.
        float addIm (float im1, float im2); // Сложение мнимой части числа.
        float getReal(); // Изъятие действительной части числа.
        float getImaginary(); // Изъятие мнимой части числа.
        
        void printNumber (); // Вывод комплексного числа.
        void initNumber(float re, float im); // Инициализация действительной и мнимой частей числа.
    private:
        float Real; // Действительная часть числа.
        float Imaginary; // Мнимая часть числа.
};
 
#endif
Собственно, сами методы.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include "stdafx.h"
#include "complex.h"
#include <iostream>
using namespace std;
 
float complex::getReal(){
    return Real;
}
 
float complex::getImaginary(){
    return Imaginary;
}
 
void complex::initNumber(float re, float im){
    Real = re;
    Imaginary = im;
}
 
void complex::printNumber(){
    cout << Real << " + " << Imaginary << "i" << endl;
}
 
float complex::addReal(float re1, float re2){
    return (re1 + re2);
}
 
float complex::addIm(float im1, float im2){
    return (im1 + im2);
}
А теперь, дамы и господа, вопросы newbie:
1) Можно ли заменить сумму и разность (для нее выписывать не буду) каким-либо отдельным методом, а не этим ужасом:
C++
1
sum.initNumber((number[num1].getReal() + number[num2].getReal()), (number[num1].getImaginary() + number[num2].getImaginary()));
Просто исходя из моих рассуждений, каждый метод класса относиться к конкретному объекту. Следовательно задействовать в методе одного объекта, данные другого возможно, но проблематично и этого делать не стоит.

2) Хотелось бы для каждого объекта сделать конструктор и деструктор не по умолчанию. Но не совсем понимаю, что туда можно засунуть кроме начальной инициализации. Подскажете?

Также буду признателен за любые замечания по поводу "гадкости" написания кода. Что нужно изменить, что подправить, чего делать категорически не стоит.

Заранее спасибо за ответы!
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
An1ka
65 / 70 / 2
Регистрация: 30.06.2011
Сообщений: 176
30.09.2011, 03:44     Простенький класс работы с комплексными числами. #2
Через перегрузку операторов:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 class Complex
{
    float re, im;
public:
    Complex( float re =0.0f, float im =0.0f) : re(re), im(im) {}
    const Complex& operator = ( const Complex& complex)
    {
        re = complex.re;
        im = complex.im;
        return *this;
    }
    Complex operator + ( const Complex& complex) const
    {
        return Complex( re + complex.re, im + complex.im);
    }
    Complex operator - ( const Complex& complex) const
    {
        return Complex( re - complex.re, im - complex.im);
    }
    Complex operator * ( const Complex& complex) const
    {
        return Complex( re * complex.re - im * complex.im, re * complex.im + im * complex.re);
    }
};
Nameless One
Эксперт С++
 Аватар для Nameless One
5754 / 3403 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
30.09.2011, 05:39     Простенький класс работы с комплексными числами. #3
Цитата Сообщение от Slimmy Посмотреть сообщение
Драйвер класса.
что такое "Драйвер класса"?

Цитата Сообщение от Slimmy Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
9
#ifndef COMPLEX_H
#define COMPLEX_H
#ifndef IOSTREAM
#define IOSTREAM
#endif
#ifndef STDAFX_H
#define STDAFX_H
#endif
//...
Зачет у тебя тут guard'ы для iostream и stdafx.h?
Где у тебя конструкторы? Где оператор присваивания? Зачем такие странные методы, как "сложишь действительные части", "сложить мнимые части", которые на самом деле выполняют одно и то же (т.е. складывают два вещественных числа)?
Где методы (или операторы), которые реализуют арифметику с самими комплексными числами?
Slimmy
 Аватар для Slimmy
65 / 18 / 2
Регистрация: 09.10.2010
Сообщений: 97
30.09.2011, 05:49  [ТС]     Простенький класс работы с комплексными числами. #4
Цитата Сообщение от Nameless One Посмотреть сообщение
что такое "Драйвер класса"?
Ну в моем понимании - это некий код, осуществляющий работу и тестирование этого самого класса.

Цитата Сообщение от Nameless One Посмотреть сообщение
Где у тебя конструкторы?
Вот как раз про них и спрашиваю. Конструктор используется по-умолчанию. Знаю, что так использовать очень и очень не хорошо.

Цитата Сообщение от Nameless One Посмотреть сообщение
Где методы (или операторы), которые реализуют арифметику с самими комплексными числами?
Проблема в том, что это до меня и не доходит. Имеем класс комплексных чисел. Он описывает один объект. То есть фактически, для того, чтобы сложить два комплексных числа нужно в одном объекте делать метод на взятие другого объекта из массива.
Может подскажете более действенную структуру класса (в плане методов, разумеется)?
Nameless One
Эксперт С++
 Аватар для Nameless One
5754 / 3403 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
30.09.2011, 05:56     Простенький класс работы с комплексными числами. #5
Цитата Сообщение от Slimmy Посмотреть сообщение
о есть фактически, для того, чтобы сложить два комплексных числа нужно в одном объекте делать метод на взятие другого объекта из массива.
нет, класс комплексных чисел ничего не должен знать ни о каких массивах.
Цитата Сообщение от Slimmy Посмотреть сообщение
Может подскажете более действенную структуру класса (в плане методов, разумеется)?
Смотри пост #2. Там уже все подсказали
Slimmy
 Аватар для Slimmy
65 / 18 / 2
Регистрация: 09.10.2010
Сообщений: 97
30.09.2011, 06:00  [ТС]     Простенький класс работы с комплексными числами. #6
Цитата Сообщение от Nameless One Посмотреть сообщение
нет, класс комплексных чисел ничего не должен знать ни о каких массивах.
Вот и я тоже так думаю.

Цитата Сообщение от Nameless One Посмотреть сообщение
Смотри пост #2. Там уже все подсказали
Это если только на будущее. Не читал еще про перегрузку операторов. Все-равно спасибо.

А можно еще вопрос? Почему Вы спросили на счет проверки включения <iostream> и "stdafx"? Её разве осуществлять не нужно? Перестраховаться там и все дела.
Nameless One
Эксперт С++
 Аватар для Nameless One
5754 / 3403 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
30.09.2011, 08:03     Простенький класс работы с комплексными числами. #7
Цитата Сообщение от Slimmy Посмотреть сообщение
Почему Вы спросили на счет проверки включения <iostream> и "stdafx"
то, что ты сделал:
  1. не нужно
    C тем, что guard'ы нужны для предотвращения повторного включения заголовочных файлов, никто не спорит. Обычно это делают так:
    C
    1
    2
    3
    4
    5
    6
    
    #ifndef ИМЯ_ХЕДЕРА_H
    #define ИМЯ_ХЕДЕРА_H
     
    // ... код хедера
     
    #endif
    И теперь сколько бы мы раз не указывали компилятору (с помощью директивы #include) подключить наш заголовочный файл, он будет подключен лишь один раз.
    Но зачем делать то же самое в своем хедере, к примеру, для iostream? Создатели твоего компилятора уже позаботились о том, чтобы iostream содержал подобные include guard'ы.
  2. скорее всего не будет работать так, как ты задумывал
    Забудем на минутку про предыдущий пункт и представим, что проверка включений стандартных заголовочных файлов в твоих заголовочных файлах является оправданным.
    Но с чего ты решил, что в iostream твоего компилятора (да и вообще, любого произвольного компилятора) защита от повторных включений осуществлена посредством определения именно символа IOSTREAM? К примеру, у меня (gcc) она осуществляется с помощью определения символа _GLIBCXX_IOSTREAM:
    C++
    1
    2
    3
    4
    5
    6
    
    #ifndef _GLIBCXX_IOSTREAM
    #define _GLIBCXX_IOSTREAM 1
     
    //...
     
    #endif
    И даже если перед включением твоего файла будет подключен iostream, то твой файл все равно никак не сможет об этом узнать.
  3. потенциально вредно
    Представим, что ты все же угадал с именем определяемого символа. Тогда рассмотрим следующую ситуацию. Имеем заголовочный файл bad_header_guard.hh:
    C++
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    #ifndef BAD_HEADER_GUARD_HH
    #define BAD_HEADER_GUARD_HH
     
    // А вот так делать очень, очень плохо!
    #ifndef _GLIBCXX_IOSTREAM
    #define _GLIBCXX_IOSTREAM
    #endif
     
    #endif
    И файл main.cc:
    C++
    1
    2
    3
    4
    5
    6
    7
    8
    
    #include "bad_header_guard.hh"
    #include <iostream>
     
    int main()
    {
        std::cout << "It seem's like there's no iostream around" << std::endl;
        return 0;
    }
    Что же произойдет, если ты попытаешься собрать эту программу? Обрабатывая main.cc, препоцессор наткнется на директиву #include "bad_header_guard.hh" на первой строке. Он обработает этот файл bad_header_guard.hh, определит символы BAD_HEADER_GUARD_HH и _GLIBCXX_IOSTREAM, и вставит его содержимое в main.cc.
    Дальше, на второй строке main.cc, ему придется обрабатывать iostream. Но, т.к. символ _GLIBCXX_IOSTREAM уже определена раньше, то содержимое iostream не будет вставлено в main.cc, т.е. препроцессор полностью его проигнорирует! И в итого мы получаем ошибку компиляции:
    Код
    -*- mode: compilation; default-directory: "/home/nameless/samples/cpp/" -*-
    Compilation started at Fri Sep 30 14:56:51
    
    make -j8
    g++ -c -Wall -g -std=c++0x main.cc
    main.cc: В функции «int main()»:
    main.cc:6:5: ошибка: «cout» не является элементом «std»
    main.cc:6:65: ошибка: «endl» не является элементом «std»
    make: *** [main.o] Ошибка 1
    
    Compilation exited abnormally with code 2 at Fri Sep 30 14:56:51
Slimmy
 Аватар для Slimmy
65 / 18 / 2
Регистрация: 09.10.2010
Сообщений: 97
30.09.2011, 16:23  [ТС]     Простенький класс работы с комплексными числами. #8
Цитата Сообщение от Nameless One Посмотреть сообщение
то, что ты сделал:
не нужно
скорее всего не будет работать так, как ты задумывал
потенциально вредно
Фактически, я еще не разбирался с директивами препроцессора и как они устроены. Просто следую "шаблону", как дрессированная собака. Через пару глав дойду, надеюсь, что буду все это понимать.
Nameless One
Эксперт С++
 Аватар для Nameless One
5754 / 3403 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
30.09.2011, 16:48     Простенький класс работы с комплексными числами. #9
Тут можно почитать про директивы препроцессора: Препроцессорные директивы в C/C++ (#include, #define и прочее)
Slimmy
 Аватар для Slimmy
65 / 18 / 2
Регистрация: 09.10.2010
Сообщений: 97
30.09.2011, 16:54  [ТС]     Простенький класс работы с комплексными числами. #10
Цитата Сообщение от Nameless One Посмотреть сообщение
Тут можно почитать про директивы препроцессора: Препроцессорные директивы в C/C++ (#include, #define и прочее)
Благодарю. Можете что-нибудь сказать о книге Харви и Пола Дейтлов? Я на данный момент её сейчас "третирую".
Nameless One
Эксперт С++
 Аватар для Nameless One
5754 / 3403 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
30.09.2011, 16:56     Простенький класс работы с комплексными числами. #11
Не читал
Slimmy
 Аватар для Slimmy
65 / 18 / 2
Регистрация: 09.10.2010
Сообщений: 97
01.10.2011, 21:23  [ТС]     Простенький класс работы с комплексными числами. #12
Если кого интересует (хотя скорее всего нет, ибо тут все образованные люди, в отличии от меня), нашел выход из ситуации с суммой. Вспомнил, про передачу объекта в метод с помощью указателя.
C++
1
2
3
4
void complex::sumNumber(complex * num1, complex * num2){
    Real = num1->getReal() + num2->getReal();
    Imaginary = num1->getImaginary() + num2->getImaginary();
}
По аналогии с разностью. Хотя, можно наверное дополнительный bool параметр передавать, который будет отвечать за выбор операции, но это уже "чисто вкусовые прибамбасы".
Nameless One
Эксперт С++
 Аватар для Nameless One
5754 / 3403 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
02.10.2011, 06:09     Простенький класс работы с комплексными числами. #13
Slimmy, если передавать объекты по значению, а не по указателю, то все равно ничего не изменится.
Slimmy
 Аватар для Slimmy
65 / 18 / 2
Регистрация: 09.10.2010
Сообщений: 97
02.10.2011, 13:09  [ТС]     Простенький класс работы с комплексными числами. #14
Цитата Сообщение от Nameless One Посмотреть сообщение
Slimmy, если передавать объекты по значению, а не по указателю, то все равно ничего не изменится.
При передаче по ссылке объект не копируется ведь, следовательно уменьшается время работы программы или я что-то путаю? Конечно, в таких "мини-прогах" на это абсолютно параллельно, но в больших проектах, где роль играет каждая сотая секунды - это принципиально, нет? Может я что-то не так понимаю.
Nameless One
Эксперт С++
 Аватар для Nameless One
5754 / 3403 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
03.10.2011, 17:47     Простенький класс работы с комплексными числами. #15
Цитата Сообщение от Slimmy Посмотреть сообщение
При передаче по ссылке объект не копируется ведь, следовательно уменьшается время работы программы или я что-то путаю?
все правильно, но тогда корректнее будет передавать либо по константой ссылке, либо по указателю на константу, т.к. передаваемые объекты не модифицируются внутри метода

Добавлено через 23 часа 26 минут
Цитата Сообщение от Nameless One Посмотреть сообщение
все правильно
ну, это если не считать того, что метод sumNumber никак не вписывается в логику класса complex. По сути, следуя из интуитивного понимания комплексных чисел, наш класс, представляющий комплексное число, должен поддерживать как минимум следующие методы (конструкторы, деструкторы и аксессоры опускаю)
  • сложения/вычитания/умножения/деления на комплексное число. Каждая операция соответствует методу, принимающему один экземпляр класса complex и возвращающему новый новое комплексное число. Пример для операции сложения:
    C++
    1
    2
    3
    4
    
    complex complex::operator + (const complex& rhs) const
    {
       return complex(re + rhs.re, im + rhs.im);
    }
  • то же самое, только для действительных чисел
  • сравнение двух комплексных чисел (равны, не равны)
  • нахождение модуля и аргумента числа
  • нахождение сопряженного комплексного числа
Вроде все...
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.10.2011, 19:56     Простенький класс работы с комплексными числами.
Еще ссылки по теме:

C++ С++ класс (создайте класс с именем Complex для выполнения в арифмитических операий с комплексными числами))
C++ c++ создать класс complex для работы с комплексными числами
C++ Реализовать класс Complex для работы с комплексными числами.

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Slimmy
 Аватар для Slimmy
65 / 18 / 2
Регистрация: 09.10.2010
Сообщений: 97
03.10.2011, 19:56  [ТС]     Простенький класс работы с комплексными числами. #16
То, что правильнее всего делать с перегрузкой операторов - это я уже понял, но пока багаж знаний не позволяет сделать это осознанно, а не по типу "да что тут думать? трясти нужно". На счет остальных добавленных методов - благодарю, сделаю. Просто делаю упражнения по книге, особо не задумываясь над содержанием.
Yandex
Объявления
03.10.2011, 19:56     Простенький класс работы с комплексными числами.
Ответ Создать тему
Опции темы

Текущее время: 17:53. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru