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

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

Восстановить пароль Регистрация
 
fuelcs
12 / 12 / 0
Регистрация: 23.01.2013
Сообщений: 143
28.08.2013, 10:36     Объекты и приведение типов #1
Добрый день.
Я написал класс, на подобии 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!
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
28.08.2013, 10:36     Объекты и приведение типов
Посмотрите здесь:

C++ Приведение типов
Приведение типов C++
C++ Приведение типов?
Приведение типов C++
Приведение типов C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
28.08.2013, 10:42     Объекты и приведение типов #2
fuelcs, Потому что
C++
1
L"!"
неявно приводится к wide_string, т.к. конструктор не является explicit, если сделать его явным (указать explicit) - то код не скомпилируется.
fuelcs
12 / 12 / 0
Регистрация: 23.01.2013
Сообщений: 143
28.08.2013, 10:44  [ТС]     Объекты и приведение типов #3
Цитата Сообщение от ForEveR Посмотреть сообщение
неявно приводится к wide_string, т.к. конструктор не является explicit.
я не совсем понимаю...

http://msdn.microsoft.com/ru-RU/library/h1y7x448.aspx
вроде понятно...
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
28.08.2013, 10:47     Объекты и приведение типов #4
fuelcs, То, что у вас написано, это так называемый conversion constructor. Там где компилятор по правилам языка может преобразовать выражение в тип, который подойдет для вызова функции - выражение будет преобразовано, если явно не указать компилятору что делать этого не надо.
fuelcs
12 / 12 / 0
Регистрация: 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"!";
Я так понимаю дело в конструкторе с параметрами?
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
28.08.2013, 11:10     Объекты и приведение типов #6
fuelcs, Можете. Но лучше бы

C++
1
+ wide_string(L"!")
fuelcs
12 / 12 / 0
Регистрация: 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();
...
CheshireCat
Эксперт С++
2907 / 1235 / 78
Регистрация: 27.05.2008
Сообщений: 3,307
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).
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
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());
Что должен будет выбрать компилятор при двух неявных операторах приведения?
CheshireCat
Эксперт С++
2907 / 1235 / 78
Регистрация: 27.05.2008
Сообщений: 3,307
28.08.2013, 16:49     Объекты и приведение типов #10
И еще, обрати внимание, что такой кусок кода скомпилируется (ура неявным преобразованиям!):
C++
1
text_3 = text_3 + 8;
Но вот будет ли действительное поведение программы соответствовать ожидаемому?
fuelcs
12 / 12 / 0
Регистрация: 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";
и позволит мне всегда контролировать что к чему я привожу...
CheshireCat
Эксперт С++
2907 / 1235 / 78
Регистрация: 27.05.2008
Сообщений: 3,307
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");
fuelcs
12 / 12 / 0
Регистрация: 23.01.2013
Сообщений: 143
28.08.2013, 17:09  [ТС]     Объекты и приведение типов #13
Цитата Сообщение от CheshireCat Посмотреть сообщение
Только надо так:
а в чем разница?
CheshireCat
Эксперт С++
2907 / 1235 / 78
Регистрация: 27.05.2008
Сообщений: 3,307
28.08.2013, 17:16     Объекты и приведение типов #14
В том, что во втором случае вероятность появления неожиданных побочных эффектов становится ниже, код ясно выражает намерения разработчика.
fuelcs
12 / 12 / 0
Регистрация: 23.01.2013
Сообщений: 143
28.08.2013, 17:28  [ТС]     Объекты и приведение типов #15
И еще вопрос, может не совсем по теме. Базовые типы данных - являются классами? Что для них приведение типа? Тут уместна аналогия, что на пример при:
C++
1
2
3
double d;
int i;
i = (int)d;
вызывается соответствующий конструктор?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.08.2013, 19:15     Объекты и приведение типов
Еще ссылки по теме:

C++ Приведение типов
Приведение типов C++
Приведение типов C++

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

Или воспользуйтесь поиском по форуму:
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
28.08.2013, 19:15     Объекты и приведение типов #16
fuelcs, Нет. Это просто приведение. Базовые типы не являются классами.
Yandex
Объявления
28.08.2013, 19:15     Объекты и приведение типов
Ответ Создать тему
Опции темы

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