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

explicit и последствия. - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 47, средняя оценка - 4.79
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
20.12.2011, 06:52     explicit и последствия. #1
Здравствуйте. Как я узнал, в С++ есть ключевое слово explicit, применяемое к конструкторам с одним параметром ( или, как я понял, большим числом параметров при условии, что все, кроме первого, имеют значения по умолчанию ) для избежания неявных преобразований типов. Возникла небольшая проблема, или скорее вопрос. Как теперь можно сделать доступной инициализацию такого вида на примере моего класса:
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
class hugeInt {
    friend std::ostream &operator<<( std::ostream &, const hugeInt & );
    friend std::istream &operator>>( std::istream &, hugeInt & );
 
public:
    explicit hugeInt();
    explicit hugeInt( const long long );
    explicit hugeInt( const char * );
    ~hugeInt();
 
    bool operator!() const;
    bool operator==( const hugeInt & ) const;
    hugeInt operator=( const hugeInt & );
    hugeInt operator=( const long long & );
 
private:
    int *numberPtr;
    size_t size;
 
    int charToDigit( const char & );
    size_t digitsInInt( const long long & );
 
    void setNum( const long long & );
    void setNum( const char * );
};
При таком объявлении и инициализации:
C++
1
2
3
4
5
6
int main()
{
    hugeInt a = 100;
 
    return 0;
}
выскакивает ошибка компиляции:
...\practice\practice\main.cpp(8): error C2440: инициализация: невозможно преобразовать "int" в "hugeInt"
1> Конструктор для class "hugeInt" объявлен как "explicit"

Подскажите, пожалуйста, можно ли при использовании explicit-конструкторов сделать возможным использования такой инициализации при объявлении? Оператор '=' перегрузил, но не помогло.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.12.2011, 06:52     explicit и последствия.
Посмотрите здесь:

C++ неоднозначность, explicit
возникнут ли последствия с динамическим массивом C++
inline explicit C++
Когда писать explicit C++
Целевой explicit конструктор C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
20.12.2011, 07:07     explicit и последствия. #2
Цитата Сообщение от Toshkarik Посмотреть сообщение
hugeInt a = 100;
Ты же сам это запретил эксплеситом. Вызывай его явно
C++
1
hugeInt a(100);
и ни каких гвоздёв.
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
20.12.2011, 07:09  [ТС]     explicit и последствия. #3
Ответ нашел на http://publib.boulder.ibm.com, похоже, что никак.

PS: Увидел только что, что создалась 2 тема, хотя у меня при первом создании темы выдало ошибку, что сервер перегружен.
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
20.12.2011, 07:43     explicit и последствия. #4
эксплисит не защищает от неявного приведения, он блокирует именно неявный вызов конструктора.
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
clas B;
class A
{
 ...
 public:
  explicit A (B &x)
  {
   ...
  }
  explicit A (B *x)
  {
   ...
  }
};
class B
{
  ...
 public:
  operator A()
  {
    ...
  }
};
B b;
A a=b; // Так нельзя
A c; // А так
c=b; // можно.
Добавлено через 5 минут
Назначение - гарантировать, что в 30-й строке не будет неоднозначности в виде возможности приведения типа конструктором временного объекта типа A с последующим присваиванием уже его объекту c. Для приведения предназначены только операторы приведения, но компиляторы не всегда это понимают. Этот оператор здесь и будет вызван, но приведение именно неявное. При декларации же самого объекта получаешь лишь синтаксическую мелочь в виде скобок вместо равенства, но инитить можно. Скобки, кстати, можно юзить и без эксплисита. А по поводу перегрузосервачнодубля темы жалуйся администрации. Для этого на форуме есть специальная тема.
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
20.12.2011, 07:48  [ТС]     explicit и последствия. #5
Цитирую из книги - "explicit позволяет подавить неявные преобразования посредством конструкторов с одним аргументом, когда такие преобразования не должны допускаться." Основной смысл работы я, в принципе, понял.
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
20.12.2011, 08:04     explicit и последствия. #6
Вот именно
Цитата Сообщение от Toshkarik Посмотреть сообщение
explicit позволяет подавить неявные преобразования посредством конструкторов
От неявного приведения оператором приведения он не защищает.
LosAngeles
Заблокирован
20.12.2011, 08:26     explicit и последствия. #7
12.3.1 Conversion by constructor
1) A constructor declared without the function-specifier explicit specifies a conversion from the types of its
parameters to the type of its class. Such a constructor is called a converting constructor.
C++
1
2
3
4
5
6
7
8
9
10
struct X {
X(int);
X(const char*, int =0);
};
void f(X arg) {
X a = 1; // a = X(1)
X b = "Jessie"; // b = X("Jessie",0)
a = 2; // a = X(2)
f(3); // f(X(3))
}
2) An explicit constructor constructs objects just like non-explicit constructors, but does so only where the
direct-initialization syntax (8.5) or where casts (5.2.9, 5.4) are explicitly used. A default constructor
may be an explicit constructor; such a constructor will be used to perform default-initialization or valueinitialization
C++
1
2
3
4
5
6
7
8
9
10
11
struct Z {
explicit Z();
explicit Z(int);
};
Z a; // OK: default-initialization performed
Z a1 = 1; // error: no implicit conversion
Z a3 = Z(1); // OK: direct initialization syntax used
Z a2(1); // OK: direct initialization syntax used
Z* p = new Z(1); // OK: direct initialization syntax used
Z a4 = (Z)1; // OK: explicit cast used
Z a5 = static_cast<Z>(1); // OK: explicit cast used
3) A non-explicit copy/move constructor (12.8) is a converting constructor. An implicitly-declared copy/move
constructor is not an explicit constructor; it may be called for implicit type conversions.
Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,898
Завершенные тесты: 1
20.12.2011, 08:36     explicit и последствия. #8
C++
1
        explicit hugeInt();
Вот тут explicit вообще не нужен.

C++
1
        hugeInt a = 100;
рассматривается как такая конструкция:
C++
1
        hugeInt a(hugeInt(100));
то есть, находится подходящий конструктор для инициализирующего литерала, затем - копирование (как бы, на самом деле всё вусмерть оптимизируется потом). Вот на вызове конструктора для создания безымянного временного объекта нам explicit и обламывает процесс.
LosAngeles
Заблокирован
20.12.2011, 08:56     explicit и последствия. #9
Цитата Сообщение от Nick Alte Посмотреть сообщение
C++
1
        hugeInt a = 100;
рассматривается как такая конструкция:
C++
1
        hugeInt a(hugeInt(100));
то есть, находится подходящий конструктор для инициализирующего литерала, затем - копирование
нет, hugeInt a = 100; равносильно hugeInt a(100); а не hugeInt a(hugeInt(100)), копирования не происходит

Добавлено через 12 минут
хотя нет, я не прав, у Nick Alte всё правильно, хотя тогда получается visual studio 2010 работает не по стандарту
Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,898
Завершенные тесты: 1
20.12.2011, 08:56     explicit и последствия. #10
Оно было бы равносильно, если бы тип литерала совпадал. А так - извините, сначала попытка неявного преобразования через соответствующий конструктор, затем копирование. Отсюда и описанная топикстартером ошибка компиляции: подходящий конструктор есть, но использовать его неявно запрещено ключевым словом explicit. Разумеется, если бы не было ограничения, потом все эти танцы с бубном всё равно оптимизировались бы в ноль до банального
C++
1
hugeInt a(100);
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
20.12.2011, 08:58  [ТС]     explicit и последствия. #11
Цитата Сообщение от Nick Alte Посмотреть сообщение
Вот тут explicit вообще не нужен.
, да, спасибо, это по не внимательности, просто разом ко всем конструкторам приписал для проверки.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.12.2011, 09:46     explicit и последствия.
Еще ссылки по теме:

explicit конструктор и перегрузки в классе C++
Динамические массивы. Последствия выхода за пределы C++
C++ Explicit и его назначение

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

Или воспользуйтесь поиском по форуму:
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
20.12.2011, 09:46     explicit и последствия. #12
Цитата Сообщение от LosAngeles Посмотреть сообщение
нет, hugeInt a = 100; равносильно hugeInt a(100); а не hugeInt a(hugeInt(100)), копирования не происходит
Это здесь. Но
C++
1
2
3
hugeInt a;
a=100; //Вот здесь будет a= hugeInt(100);
// То есть вызывается сначала конструктор безымянного временного объекта, потом копирующее присваивания, а потом ещё и деструктор безымянного временного объекта. Вот чтоб гарантировать вызов вместо всего этого оператора присваивания с преобраованием (hugeInt operatro = (int x); - это присваивание именно с преобразованием) используется эксплисит. А при наличии оператора приведения в исходном типе к целевому отработает он, а потом копирующее присваивание, в обоих случаях не будет вызван ни конструктор, ни деструктор
Yandex
Объявления
20.12.2011, 09:46     explicit и последствия.
Ответ Создать тему
Опции темы

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