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

Класс "вектор" с конструкторами, позволяющими создать нулевой вектор и вектор с произвольным числом элементов - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 5.00
__sirroko
4 / 4 / 3
Регистрация: 03.03.2013
Сообщений: 55
06.03.2014, 00:13     Класс "вектор" с конструкторами, позволяющими создать нулевой вектор и вектор с произвольным числом элементов #1
Привет!

Задача следующая.
Нужно реализовать класс "вектор" с конструкторами, которые позволяют создать нулевой вектор и вектор с произвольным кол-во элементов. И требуется перегрузить ряд операций.

Пока что перегружены [], =, +. Но где-то ошибка и я не понимаю где.

При варианте
C++
1
CVector v3 = v2;
ошибок нет, а, если так сделать
C++
1
CVector v3 = v2 + v1;
компилятор начинает ругаться.

Вот код и вывод комплятора =)

main.cpp
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
#include "CVector.h"
 
#include <iostream>
using namespace std;
 
#define N 10
 
void PrintVector(char *str, CVector &obj)
{
    cout << str << " :: ";
    for (int i = 0; i < obj.GetSize(); i++)
        cout << obj[i] << " ";
    cout << endl;
}
 
int main(int argc, char *argv[])
{
    int *a = new int[N];
 
    for (int i = 0; i < N; i++)
        a[i] = i*11;
 
    CVector v1(N, a);
    PrintVector("v1", v1);
 
    CVector v2(v1);
    PrintVector("v2", v2);
 
    CVector v3 = v1 + v2;
    PrintVector("v3 = v1 + v2", v3);
 
    return 0;
}
CVector.cpp
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include "CVector.h"
 
#include <iostream>
#include <cstdlib>
using namespace std;
 
CVector::CVector(int s, int *arg)
{
    if (s <= 0) {
        cout << "Размерность вектора указана неправильно!\n";
        return;
    }
 
    size = s;
    p_vector = new int[s];
 
    for (int i = 0; i < size; i++)
        p_vector[i] = arg[i];
}
 
CVector::CVector(CVector &obj)
{
    size = obj.size;
    p_vector = new int[obj.size];
 
    for (int i = 0; i < size; i++)
        p_vector[i] = obj.p_vector[i];
}
 
void CVector::InitVector(int s, int *arg)
{
    if (p_vector) delete [] p_vector;
 
    size = s;
    p_vector = new int[s];
 
    for (int i = 0; i < size; i++)
        p_vector[i] = arg[i];
}
 
int &CVector::operator[](int i)
{
    if (i < 0 || i > (size - 1)) {
        cout << "Неверный индекс.\n";
        exit(1);
    }
 
    return p_vector[i];
}
 
CVector CVector::operator=(CVector obj)
{
    // Если размеры векторов не совпадают, то
    // выделяется память нужного размера
    if (size != obj.size) {
        delete [] p_vector;
        p_vector = new int[obj.size];
        size = obj.size;
    }
 
    for (int i = 0; i < size; i++)
        p_vector[i] = obj.p_vector[i];
 
    return *this;        
}
 
CVector CVector::operator+(CVector obj)
{
    CVector tmp = *this;
 
    if (tmp.size == obj.size) {
        for (int i = 0; i < tmp.size; i++)
            tmp.p_vector[i] += obj.p_vector[i];
    } else {
        cout << "Вектора разной размерности." << endl;
        exit(1);
    }
 
    return tmp;
}
CVector.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class CVector
{
    int *p_vector;
    int size;
 
public:
    CVector() { size = 0; p_vector = 0; }
    CVector(int s, int *arg);
    CVector(CVector &obj);
    ~CVector() { if (p_vector) delete [] p_vector; }
 
    void InitVector(int s, int *arg);
    int GetSize() { return size; }
 
    int &operator[](int i);
    CVector operator=(CVector obj);
    CVector operator+(CVector obj);
};
Bash
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
main.cpp: In function ‘int main(int, char**)’:
main.cpp:24:25: warning: deprecated conversion from string constant to ‘char*[-Wwrite-strings]
     PrintVector("v1", v1);
                         ^
main.cpp:27:25: warning: deprecated conversion from string constant to ‘char*[-Wwrite-strings]
     PrintVector("v2", v2);
                         ^
main.cpp:29:23: error: no matching function for call to ‘CVector::CVector(CVector)’
     CVector v3 = v1 + v2;
                       ^
main.cpp:29:23: note: candidates are:
In file included from main.cpp:1:0:
CVector.h:9:5: note: CVector::CVector(CVector&)
     CVector(CVector &obj);
     ^
CVector.h:9:5: note:   no known conversion for argument 1 from ‘CVector’ to ‘CVector&’
CVector.h:8:5: note: CVector::CVector(int, int*)
     CVector(int s, int *arg);
     ^
CVector.h:8:5: note:   candidate expects 2 arguments, 1 provided
CVector.h:7:5: note: CVector::CVector()
     CVector() { size = 0; p_vector = 0; }
     ^
CVector.h:7:5: note:   candidate expects 0 arguments, 1 provided
main.cpp:30:35: warning: deprecated conversion from string constant to ‘char*[-Wwrite-strings]
     PrintVector("v3 = v1 + v2", v3);
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.03.2014, 00:13     Класс "вектор" с конструкторами, позволяющими создать нулевой вектор и вектор с произвольным числом элементов
Посмотрите здесь:

C++ Создать класс – вектор
C++ Создать иерархию классов вектор(longint) и безопасный вектор с проверкой выхода за пределы
Создать абстрактный тип данных - класс вектор, который имеет указатель на long, число элементов и переменную состояния C++
Перегрузка функции(Создать класс Vector – вектор.) C++
Считать вектор из файла, записать вектор в файл C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
06.03.2014, 00:25     Класс "вектор" с конструкторами, позволяющими создать нулевой вектор и вектор с произвольным числом элементов #2
пока не придумал почему там при конверсии какие-то неоднозначности, но решение может быть таким:
сигнатуры функций нужно подправить. если функция работает с толстым объектом и не модифицирует его,
то желательно его передавать по константной ссылке (если нет мува по крайней мере):
CVector(const CVector &obj);
CVector& operator=(const CVector& obj);
CVector operator+(const CVector& obj) const;
__sirroko
4 / 4 / 3
Регистрация: 03.03.2013
Сообщений: 55
06.03.2014, 22:46  [ТС]     Класс "вектор" с конструкторами, позволяющими создать нулевой вектор и вектор с произвольным числом элементов #3
Помогло, спасибо большое!

Если поймете как объяснить возникающую неоднозначность, то с удовольствием послушаю.
castaway
Эксперт С++
4837 / 2976 / 367
Регистрация: 10.11.2010
Сообщений: 11,008
Записей в блоге: 10
Завершенные тесты: 1
07.03.2014, 00:04     Класс "вектор" с конструкторами, позволяющими создать нулевой вектор и вектор с произвольным числом элементов #4
После изменений какие предупреждения выдаёт?
Тут тоже следует подправить: void PrintVector( const char * str, CVector & obj )
DrOffset
6419 / 3793 / 877
Регистрация: 30.01.2014
Сообщений: 6,581
07.03.2014, 00:12     Класс "вектор" с конструкторами, позволяющими создать нулевой вектор и вектор с произвольным числом элементов #5
warning: deprecated conversion from string constant to ‘char*’
Означает, неявное преобразование из константного массива символов к указателю на неконстантный массив символов объявлено запрещенным к использованию. Это логично. Ибо через такой указатель можно будет поменять константную строку, что приведет UB (undefined behaviour, google it).
error: no matching function for call to ‘CVector::CVector(CVector)’
CVector v3 = v1 + v2;
Операция сложения создает временный объект. Временный объект - это rvalue (google it). Преобразование rvalue к неконстантной ссылке запрещено, поэтому он пытается найти конструктор, который принимает вектор по значению, но не находит - отсюда ошибка.
no known conversion for argument 1 from ‘CVector’ to ‘CVector&’
Говорит как раз о запрете, который я озвучил выше.

Советы:
там, где вектор не изменяется - его следует передавать по константной ссылке.
методы, которые не изменяют состояние объекта вектора, следует помечать как const (в примере DU это есть).
функция exit крайне не рекомендуется к использованию в программах на С++, т.к. выход из программы игнорирует все конструкторы уже созданных объектов, что может приводить к утечкам ресурсов (для спорщиков: да, я знаю, что память отдается системе после выхода, но память не единственный ресурс).
для operator[] принято реализовывать две версии, неконстантную и константную (не позволяет менять объекты внутри вектора, только читать).

Есть еще замечания, но по сравнению с озвученным - это уже придирки.
__sirroko
4 / 4 / 3
Регистрация: 03.03.2013
Сообщений: 55
07.03.2014, 01:21  [ТС]     Класс "вектор" с конструкторами, позволяющими создать нулевой вектор и вектор с произвольным числом элементов #6
castaway, если подправить PrintVector, тоже больше никаких предупреждений не выводится.

DrOffset, с UB и rvalue более менее понятно. С exit - тоже.

Всем большое спасибо!
Yandex
Объявления
07.03.2014, 01:21     Класс "вектор" с конструкторами, позволяющими создать нулевой вектор и вектор с произвольным числом элементов
Ответ Создать тему
Опции темы

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