{return Complex(Re-X.Re,Im-X.Im);}
Complex operator *(Complex X,Complex Y)
{
return Complex(X.Re*Y.Re-X.Im*Y.Im, X.Re*Y.Im+Y.Re*X.Im);
}
Проверка корректности значения указателя ObjName в деструкторе выполнена для того, чтобы избежать ошибки времени выполнения в некоторых сложных случаях.
Теперь внимательно проанализируйте результаты выполнения следующего программного кода. В комментариях приведены результаты работы макросов TRACE.
Void main()
{
{
Complex a (1.23,4," a " ), b (2.34,5," b " ), c (0,0," C " );
//Complex ObjName=a this=1244980
//Complex ObjName=b this=1244948
//Complex ObjName=C this=1244916
c=a+b;
//CopyCTR Org.ObjName=b this=1244604
//Complex ObjName=Return operator+ this=1244628
//~Complex ObjName=b this=1244604
//operator= Org.ObjName=Return operator+ this=1244824
//~Complex ObjName=Return operator+ this=1244628
//CopyCTR Org.ObjName=C this=1244624
//~Complex ObjName=C this=1244624
// Если параметр операции-функции сложения объявить ссылкой
// Complex operator +(Complex &X),
// то получим такую последовательность вызовов методов:
//Complex ObjName=Return operator+ this=1244648
//operator= Org.ObjName=Return operator+ this=1244916
//~Complex ObjName=Return operator+ this=1244648
//CopyCTR Org.ObjName=C this=1244644
//~Complex ObjName=C this=1244644
// Если операцию-функцию присвоить объявить как
// Complex & operator=(const Complex & Org)
// (и при этом операцию-функцию сложения объявить как
// Complex operator +(Complex &X),
// то получим такую последовательность вызовов методов:
//Complex ObjName=Return operator+ this=1244680
//operator= Org.ObjName=Return operator+ this=1244916
//~Complex ObjName=Return operator+ this=1244680
cout<<c<<endl;
//CopyCTR Org.ObjName=C this=1244624
//~Complex ObjName=C this=1244624
}
//~Complex ObjName=C this=1244916
//~Complex ObjName=b this=1244948
//~Complex ObjName=a this=1244980
}
Для того чтобы отследить порядок вызова конструкторов и деструктора, необходимо выполнить трассировку программы, причем с заходом в функции.
Какие можно сделать основные выводы из результатов выполнения этой программы, точнее, реализации операций-функций?
Во-первых, если объект передается в функцию как параметр-значение, то его копия создается с помощью конструктора копирования. Это значит, что если реализация конструктора копирования по умолчанию нас не устраивает, то требуется разработать его корректную реализацию. Например, если среди член-данных класса есть указатели и для них выделяется динамическая память, то требуется разработать корректный конструктор копирования. Также стоит отметить, что конструктор копирования вызывается и при возврате объекта из функции с помощью оператора return.
В качестве еще одного примера рассмотрим класс CArr, предназначенный для обработки одномерных массивов.
Реализация операции вычитания массивов, как и других полезных операций, отдана на ваше усмотрение. После выполнения этой работы использование объектов класса может быть реализовано следующим образом:
Void main()
{
setlocale(LC_ALL,"rus");
srand( (unsigned)time( NULL ) );
int N=7;
CArr A(N,"A");
CArr B(N,"B"),*C;
for(int i=0;i<N;i++)
{
double Val=(double)rand()/RAND_MAX*10;
A.setElem(i,Val);
Val=(double)rand()/RAND_MAX*10;
B.setElem(i,Val); // можно так
B[i]=Val; // а можно и так
}
cout<<" Массив А " <<endl<<A<<endl<<endl;
cout<<" Массив B" <<endl<<B<<endl<<endl;
C=A+B;
cout<<" Массив C=A+B" <<endl<<*C<<endl<<endl;
delete C;
CArr D(N,"D");
D=A-B;
cout<<" Массив D=A-B" <<endl<<D <<endl<<endl;
cout<<" Массив A-B" <<endl<<(A-B)<<endl<<endl;
}
Варианты заданий
В приведенных ниже вариантах заданий под векторами подразумеваются одномерные массивы, а под матрицами – двумерные.
Значения элементов векторов и матриц должны иметь вещественный тип; их необходимо генерировать с помощью датчика псевдослучайных чисел из заданного пользователем диапазона.
Выбор варианта задания согласуйте с преподавателем.
Таблица 1
Варианты заданий
Вариант | Задание |
1 | Реализовать операции сложения и вычитания двух прямоугольных матриц одинакового размера |
2 | Реализовать операцию транспонирования прямоугольной матрицы. Например, если для этой операции выбрать знак ~, то программа должна позволять вычислять выражения вроде A=~B. Понятно, что если матрица А имеет размер 3х4, то матрица В должна иметь размер 4х3 |
3 | Реализовать операцию умножения двух прямоугольных матриц. Две матрицы можно перемножить, если число столбцов первой матрицы равно числу строк второй. Например, если первая матрица имеет размер 3х4, а вторая 4х2, то получим результирующую матрицу 3х2 |
4 | Реализовать операцию умножения матрицы на заданную величину, а также сложения матрицы с заданной величиной |
5 | Реализовать операцию умножения матрицы на вектор. Например, если имеется матрица размером 3х4 и вектор размером 4, то в результате должен получиться вектор размером 3. Матрица и вектор должны быть реализованы как разные классы |
6 | Реализовать операции сложения и умножения векторов, для чего необходимо разработать два разных класса: один с данными вещественного типа, а другой – целого |
7 | Реализовать операцию прямого (внешнего) произведения двух прямоугольных матриц одинакового размера С=А*В. Элементы матрицы С являются произведением соответствующих элементов матриц А и В: С[i][j]=A [i][j]*B[i][j] |
8 | Реализовать операцию нормирования вектора путем приведения его значений к диапазону от -1 до +1 |
9 | Реализовать операцию умножения матрицы на вектор. Например, если имеется матрица размером 3х4 и вектор размером 4, то в результате должен получиться вектор размером 3 |
10 | Реализовать операции вычитания и деления векторов и проиллюстрировать возможность вычисления выражений вроде a=(b-c)/d, где a, b, c и d – векторы |
11 | Реализовать операции сложения и вычитания двух треугольных матриц одинакового размера |
Дата: 2019-07-30, просмотров: 226.