Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/5: Рейтинг темы: голосов - 5, средняя оценка - 5.00
12 / 12 / 2
Регистрация: 23.01.2013
Сообщений: 143
1

Объекты и приведение типов

28.08.2013, 10:36. Показов 1005. Ответов 15
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день.
Я написал класс, на подобии std::string, только для типа wchar_t. Вот сам класс:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#pragma once
#include <iostream>
class wide_string
{
public:
    wide_string(void);
    wide_string(const wchar_t *data);
    wide_string(const wide_string &copy);
    ~wide_string(void);
    wide_string& operator = (const wide_string &copy);
    wide_string& operator + (const wide_string &copy);
    wide_string& operator + (const unsigned &number);
    operator wchar_t*();
private:
    wchar_t *data;
    size_t size;
    size_t digits_count (unsigned number);
};
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include "wide_string.h"
 
wide_string::wide_string(void)
{
    data = NULL;
    size = 0;
}
 
wide_string::wide_string(const wchar_t *data)
{
    size = wcslen(data);
    this->data = new wchar_t [size + 1];
    wcscpy_s(this->data, size+1,data);
}
 
wide_string::wide_string(const wide_string &copy)
{
    size = wcslen(copy.data);
    this->data = new wchar_t [size + 1];
    wcscpy_s(data, size+1, copy.data);
}
 
wide_string::~wide_string(void)
{
    if (data)
    {
        delete [] data;
        size = 0;
    }
}
 
wide_string& wide_string::operator = (const wide_string &copy)
{
    if (this!=&copy)
    {
        size = copy.size;
        if (data)
        {
            delete [] data;
        }
        this->data = new wchar_t [size + 1];
        wcscpy_s(data, size + 1, copy.data);
    }
    return *this;
}
 
wide_string& wide_string::operator + (const wide_string &copy)
{
    size_t temp_size = size + copy.size;
    wchar_t *temp = NULL;
    if (temp_size > 1)
    {
        temp = new wchar_t [temp_size + 1];
        wcscpy_s(temp, temp_size + 1, data);
        wcscat_s(temp, temp_size + 1, copy.data);
        if (data)
        {
            delete [] data;
        }
        size = temp_size;
        data = new wchar_t [size + 1];
        wcscpy_s(data, size +1 , temp);
    }
    return *this;
}
 
wide_string& wide_string::operator + (const unsigned &number)
{
    size_t temp_size = digits_count(number);
    wchar_t *temp = NULL;
    if (temp_size > 0)
    {
        temp = new wchar_t [temp_size + 1];
        _itow_s(number, temp, temp_size + 1, 10);
        if (data)
        {
            wchar_t *copy = NULL;
            copy = new wchar_t [size + 1];
            wcscpy_s(copy, size + 1, data);
            delete [] data;
            size += temp_size;
            data = new wchar_t [size + 1];
            wcscpy_s(data, size + 1, copy);
            wcscat_s(data, size + 1, temp);
        }
        else
        {
            size += temp_size;
            data = new wchar_t [size + 1];
            wcscpy_s(data, size + 1, temp);
        }
        
    }
    return *this;
}
 
wide_string::operator wchar_t*()
{
    return data;
}
 
size_t wide_string::digits_count (unsigned number)
{
    size_t count = 1;
    while (number/=10)
    {
        count++;
    }
    return count;
}
Вопрос: почему в выражении:
C++
1
2
wide_string text_3(L"Кількість спроб рівна ");
text_3 = text_3 + L"!";
компилятор не выдает ошибку? Ведь я не перегружал оператор "плюс" для wchar_t!
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
28.08.2013, 10:36
Ответы с готовыми решениями:

Приведение типов
Доброго времени суток. Данный кусок кода выделяет целую часть. Потом, вычитая из исходного числа...

Приведение типов
Уважаемые программеры, ПОМОГИТЕ!!! Нужно (мне) реализовать шаблонную функцию для приведения типов....

Приведение типов
Как привести наследника ко второму родителю? class Parent1 { public: int a; int b; ...

Приведение типов
Доброго времени суток. Пусть имеются две структуры struct Student { string FirstName;...

15
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
28.08.2013, 10:42 2
fuelcs, Потому что
C++
1
L"!"
неявно приводится к wide_string, т.к. конструктор не является explicit, если сделать его явным (указать explicit) - то код не скомпилируется.
1
12 / 12 / 2
Регистрация: 23.01.2013
Сообщений: 143
28.08.2013, 10:44  [ТС] 3
Цитата Сообщение от ForEveR Посмотреть сообщение
неявно приводится к wide_string, т.к. конструктор не является explicit.
я не совсем понимаю...

http://msdn.microsoft.com/ru-R... 7x448.aspx
вроде понятно...
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
28.08.2013, 10:47 4
fuelcs, То, что у вас написано, это так называемый conversion constructor. Там где компилятор по правилам языка может преобразовать выражение в тип, который подойдет для вызова функции - выражение будет преобразовано, если явно не указать компилятору что делать этого не надо.
1
12 / 12 / 2
Регистрация: 23.01.2013
Сообщений: 143
28.08.2013, 10:52  [ТС] 5
ForEveR,
а так я могу сделать?
C++
1
2
3
...
explicit wide_string(const wchar_t *data);
...
а в коде функции:
C++
1
text_3 = text_3 + (wide_string)L"!";
Я так понимаю дело в конструкторе с параметрами?
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
28.08.2013, 11:10 6
fuelcs, Можете. Но лучше бы

C++
1
+ wide_string(L"!")
0
12 / 12 / 2
Регистрация: 23.01.2013
Сообщений: 143
28.08.2013, 16:05  [ТС] 7
ForEveR, Если я правильно понял суть, то можно перегрузить конструктор с параметрами для различных типов данных, а оператор плюс перегрузить только для объектов класса?
Было:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class wide_string
{
public:
    wide_string(void);
    wide_string(const wchar_t *data);
    wide_string(const wide_string &copy);
    ~wide_string(void);
    wide_string& operator = (const wide_string &copy);
    wide_string& operator + (const wide_string &copy);
    wide_string& operator + (const unsigned &number);
    operator wchar_t*();
private:
    wchar_t *data;
    size_t size;
    size_t digits_count (unsigned number);
};
Стало:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class wide_string
{
public:
    wide_string(void);
    wide_string(const wchar_t *data);
    
    wide_string(const unsigned data);
    wide_string(const char *data);
    ...
    
    wide_string(const wide_string &copy);
    ~wide_string(void);
    wide_string& operator = (const wide_string &copy);
    wide_string& operator + (const wide_string &copy);
    operator wchar_t*();
private:
    wchar_t *data;
    size_t size;
    size_t digits_count (unsigned number);
};
Добавлено через 3 минуты
Еще есть вопрос, можно ли перегрузить Conversion Function?
Например:
C++
1
2
3
operator wchar_t*();
operator int();
...
0
Эксперт С++
2924 / 1274 / 114
Регистрация: 27.05.2008
Сообщений: 3,465
28.08.2013, 16:12 8
operator+ необходимо перегрузить таким образом, чтобы он мог принимать участие в выражениях:
C++
1
2
text_3 = text_3 + L"!";    // это скомпилируется
text_3 = L"?" + text_3;    // а это - нет
Т.е. необходимы две версии - одна в форме функции класса wide_string& operator + (const wide_string &right), и здесь будет использовано неявное преобразование, другая в форме внешней функции wide_string& operator + (const wchar_t* left, const wide_string &right).
1
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
28.08.2013, 16:14 9
fuelcs, (void) в С++ писать не нужно. Лишнее и абсолютно бессмысленное занятие.
У вас конструкторы не explicit, поэтому будет вполне себе компилироваться такой код:
C++
1
2
wide_string ws(L"1");
ws = ws + "2";
Да, conversion операторы перегрузить можно, но не стоит оно того, чес слово. Или хотя бы юзать explicit для них, который появился только в С++11.
C++
1
2
3
4
void function(int) {}
void function(wchar_t*) {}
 
function(wide_string());
Что должен будет выбрать компилятор при двух неявных операторах приведения?
1
Эксперт С++
2924 / 1274 / 114
Регистрация: 27.05.2008
Сообщений: 3,465
28.08.2013, 16:49 10
И еще, обрати внимание, что такой кусок кода скомпилируется (ура неявным преобразованиям!):
C++
1
text_3 = text_3 + 8;
Но вот будет ли действительное поведение программы соответствовать ожидаемому?
0
12 / 12 / 2
Регистрация: 23.01.2013
Сообщений: 143
28.08.2013, 17:01  [ТС] 11
Цитата Сообщение от CheshireCat Посмотреть сообщение
Но вот будет ли действительное поведение программы соответствовать ожидаемому?
будет! у меня в программе почти так и есть...

То есть окончательный вариант такой:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class wide_string
{
public:
    wide_string(void);
    explicit wide_string(const wchar_t *data);
    
    explicit wide_string(const unsigned data);
    explicit wide_string(const char *data);
    ...
    
    wide_string(const wide_string &copy);
    ~wide_string(void);
    wide_string& operator = (const wide_string &copy);
    wide_string& operator + (const wide_string &copy);
    explicit operator wchar_t*();
private:
    wchar_t *data;
    size_t size;
    size_t digits_count (unsigned number);
};
что мне позволит без перегрузки глобальных операторов писать так:

C++
1
2
unsigned some_variable = 0;
text_3 = text_3 + (wide_string) some_variable  + (wide_string) L"some text";
и позволит мне всегда контролировать что к чему я привожу...
0
Эксперт С++
2924 / 1274 / 114
Регистрация: 27.05.2008
Сообщений: 3,465
28.08.2013, 17:08 12
Только надо так:
C++
1
2
unsigned some_variable = 0;
text_3 = text_3 + wide_string(some_variable)  + wide_string(L"some text");
1
12 / 12 / 2
Регистрация: 23.01.2013
Сообщений: 143
28.08.2013, 17:09  [ТС] 13
Цитата Сообщение от CheshireCat Посмотреть сообщение
Только надо так:
а в чем разница?
0
Эксперт С++
2924 / 1274 / 114
Регистрация: 27.05.2008
Сообщений: 3,465
28.08.2013, 17:16 14
В том, что во втором случае вероятность появления неожиданных побочных эффектов становится ниже, код ясно выражает намерения разработчика.
0
12 / 12 / 2
Регистрация: 23.01.2013
Сообщений: 143
28.08.2013, 17:28  [ТС] 15
И еще вопрос, может не совсем по теме. Базовые типы данных - являются классами? Что для них приведение типа? Тут уместна аналогия, что на пример при:
C++
1
2
3
double d;
int i;
i = (int)d;
вызывается соответствующий конструктор?
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
28.08.2013, 19:15 16
fuelcs, Нет. Это просто приведение. Базовые типы не являются классами.
0
28.08.2013, 19:15
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
28.08.2013, 19:15
Помогаю со студенческими работами здесь

Приведение типов
Чем отличается type(x) от (type) x?

Приведение типов
При вводе с клавиатуры s = 11 и a = 1.1, получаем 9. Результат переменной d = 10, это правильно. В...

Приведение типов
Есть код вызова метода: obj.func(char a, char b) сам метод: void func(char a, char b) { int i...

Приведение типов
Необходимо привязать адрес массива double по указателю к адресу структуры. Массив сам создан в...


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

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru