1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886

Conversion by constructor , нужны пояснения

29.04.2017, 04:11. Показов 2233. Ответов 17
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте.
Смотрю я, что пишут об этом Conversion by constructor, вижу одно:
Конструктор C++, который принимает один аргумент, определяет преобразование типа аргумента в тип класса.
Вот, думаю, сейчас как заставлю компилятор обломаться при компиляции:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
 
class MyClass {
    int a;
public:
  MyClass(int i):a(i) { };
  int get() const { return a; }
};
 
 
int main() {
  MyClass obj1(100); //int должен привестись к MyClass
 
  //Но в int нельзя присваивать объекты типа MyClass
  //Что не мешает уходящему int приходить в параметр
 
}
В аргументе тип int, который, по некоторой логике, происходящей из утверждений, подобных в приведённой цитате, преобразуется в тип MyClass, но тут возникает вопрос, а почему же пример работает? Ведь нельзя в этом коде присвоить в int объект типа MyClass.

______________
Просьба расставить все точки над Иъ и немного исправить моё искажённое восприятие такого конструктора.

Ещё бы мне не помешал маленький и простой пример, где такое преобразование, которое запрещается explicit, оказывается не к месту.
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
29.04.2017, 04:11
Ответы с готовыми решениями:

Expected constructor, destructor, or type conversion before '.' token
struct Gf3 { GLfloat x; GLfloat y; GLfloat z; } p1,p2,p3,t; t.x = 0.0; t.y = 0.0; t.z = 1.0; p1.x = 0.0; p1.y =...

Ошибка expected constructor, destructor, or type conversion before '(' toke
Возникает ошибка expected constructor, destructor, or type conversion before '(' toke в 7 и 16 строчке. #include &lt;iostream&gt; ...

Ошибка expected constructor, destructor, or type conversion before ';' token
выдает ошибку expected constructor, destructor, or type conversion before ';' token с 61-90 строчку.че делать уже не знаю.проверяла код ...

17
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
29.04.2017, 04:13
Цитата Сообщение от daslex Посмотреть сообщение
MyClass obj1(100); //int должен привестись к MyClass
вы ошибаетесь.
здесь нет преобразований типов.


преобразования - конструкции вида:
C++
1
MyClass obj1 = 100;
1
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
29.04.2017, 04:18  [ТС]
Цитата Сообщение от daslex Посмотреть сообщение
определяет преобразование типа аргумента в тип класса.
А это о чём? Переведите на русский, пожалуйста.

Добавлено через 1 минуту

Не по теме:

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

0
nd2
3438 / 2817 / 1249
Регистрация: 29.01.2016
Сообщений: 9,427
29.04.2017, 04:25
Цитата Сообщение от daslex Посмотреть сообщение
А это о чём?
Цитата Сообщение от hoggy Посмотреть сообщение
MyClass obj1 = 100;
О том, что при таком преобразовании будет использован конструктор с одним аргументом, которому будет передано число 100.
1
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
29.04.2017, 04:32  [ТС]
MyClass obj1(100);

MyClass obj1 = 100; //Так я и хотел, не доглядел, не доправил...
Но это суть не меняет. Ошибка из другого леса.

Добавлено через 6 минут
Цитата Сообщение от nd2 Посмотреть сообщение
О том, что при таком преобразовании
А ещё о чём? На таких условиях жёсткого требования таким конструкторам явно указывать explicit едва ли достаточно.

И не при таком преобразовании, а всё-таки при таком конструкторе, тут как бы порядок имеет значение, полагаю.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
29.04.2017, 04:34
http://rextester.com/UULKO63674

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
 
class MyClass {
    int a;
public:
    
  // умеет построиться из int
  MyClass(int i):a(i) {};
    
    
  // умеет привестись к int  
  operator int()const { return a; }
};
 
 
int main() 
{
  MyClass obj = 100;
 
  std::cout << "неявное приведение MyClass к int: " 
      << obj << std::endl;
 
}
1
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
29.04.2017, 04:41  [ТС]
Не то. Меня интересует только конструктор. То, что он умеет построится из int я знаю, о conversion function я тоже знаю, и она явно не конструктор.

Добавлено через 1 минуту
Что обозначает определить преобразование типа аргумента в тип класса - не понимаю.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
29.04.2017, 04:42
Цитата Сообщение от daslex Посмотреть сообщение
Что обозначает определить преобразование типа аргумента в тип класса - не понимаю.
создать объект класса, проинициализированный конструктором с параметром.
1
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
29.04.2017, 04:52  [ТС]
Пример попроще, когда это преобразование оказывается вредным, можно?
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
29.04.2017, 04:56
Цитата Сообщение от daslex Посмотреть сообщение
Пример попроще, когда это преобразование оказывается вредным, можно?
http://rextester.com/YWKHU74133

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
#include <iostream>
using namespace std;
 
 
struct foo {}; //<--- не умеет выводится в поток
 
struct bar  //<--- умеет выводится в поток
{
    template<class T> using Stream = ::std::basic_ostream<T>;
    
    template<class T> friend
        Stream<T>& operator<<(Stream<T>& os, const bar& obj ) { return os<<"bar"; }
    
    bar(){}
    bar(const foo&){} //<--- и может построится на основании foo, 
    //который не умеет выводится в поток
};
 
 
 
int main()
{
    std::cout << "Hello, world!\n";
    
    const foo f;
    const bar b;
    
    cout << b << endl;  //<--- здесь все нормально и предсказуемо
    
    
    cout << f << endl; //<--- а вот здесь лажа
    
    //компилятор гцц почему то считает, что раз foo не умеет выводиться в поток,
    //значит можно взять любую перегрузку, аргумент которой может построится из foo
    //и использовать её
    
    //по итогу получаем сюрприз: строительство временного объекта
    //                           и вывод в поток совершенно не того типа, 
    //                           который по смыслу нужно было выводить
    
}
0
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
29.04.2017, 17:43  [ТС]
Вряд ли этот пример можно назвать примером попроще. К тому же ни один из домашних моих компиляторов его не осилил.

Добавлено через 12 часов 41 минуту
Вопрос не решён.
0
19426 / 10042 / 2447
Регистрация: 30.01.2014
Сообщений: 17,709
29.04.2017, 19:12
Цитата Сообщение от daslex Посмотреть сообщение
Ещё бы мне не помешал маленький и простой пример, где такое преобразование, которое запрещается explicit, оказывается не к месту.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class C
{
public:
    C(bool a) {}
};
 
void foo(C const & x)
{
}
 
int main()
{
    int * ptr = 0;
    foo(ptr);
}
По вызову создается впечатление, что в функцию передается указатель. Хотя на самом деле будет неявное преобразование к С через конструктор c bool (любой указатель неявно приводится к bool, как мы все знаем). В общем, это может быть совсем не тем, что мы в итоге ожидаем.
1
132 / 158 / 87
Регистрация: 06.04.2016
Сообщений: 992
29.04.2017, 19:24
Цитата Сообщение от daslex Посмотреть сообщение
В аргументе тип int, который, по некоторой логике, происходящей из утверждений, подобных в приведённой цитате, преобразуется в тип MyClass, но тут возникает вопрос, а почему же пример работает? Ведь нельзя в этом коде присвоить в int объект типа MyClass.
- Вы уж извините, бред какой-то пишите, сами написали в параметре конструктора тип int, потом передаете целое число 100(что правильно) и при чем тут преобразование int-to-MyClass и ошибка компилятора. Ему неначем ошибаться. Вы там уже перезанимались по-моему.

Добавлено через 3 минуты
Цитата Сообщение от DrOffset Посмотреть сообщение
любой указатель неявно приводится к bool
- первый раз слышу.
0
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
29.04.2017, 20:10  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
В общем, это может быть совсем не тем, что мы в итоге ожидаем.
Увы, но я не вижу ответа.

Если указатель умеет приводиться к bool, то этот пример мало отличается от такого:
C++
1
2
3
4
5
6
7
void foo(int x){}
 
int main()
{
    double a = 100;
    foo(a);
}
Конструктор тут ни при чём, наверное.
0
19426 / 10042 / 2447
Регистрация: 30.01.2014
Сообщений: 17,709
29.04.2017, 20:43
Цитата Сообщение от daslex Посмотреть сообщение
то этот пример мало отличается от такого
Нет, сильно отличается.
Я этот пример привел не от балды. Это было реальной проблемой в реальном проекте.
Тут в твоем примере только одно преобразование. А в моем - два. И это в добавок к тому, что мы получаем совсем другое поведение, совершенно отличное от внешне ожидаемого: у нас же нет конструктора для указателя.

Зачем вообще нужен explicit? Простой ответ - чтобы запретить неявное преобразование. Но зачем может быть нужно запрещать неявное преобразование? Чтобы подчеркнуть смысловое различие используемых сущностей.
Иными словами, если мы пишем:
C++
1
String str(2);
мы понимаем, что это строка, размером 2.
А если мы пишем
C++
1
String str = 2;
то как бы получается, что наша строка - это 2.
И, естественно, вызывая функцию с параметром String
C++
1
void foo(String const &)
мы бы наверняка не хотели, чтобы такое компилировалсь:
C++
1
foo(2);
потому что это противоречит заданному нами смыслу для класса String. Стоял бы у конструктора с целочисленным аргументом explicit - компилятор не допустил бы такое использование. С другой стороны, вот такая запись:
C++
1
String str = "12345";
не противоречит назначению класса String, а значит конструктор для char const * делать explicit нет смысла.
3
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
29.04.2017, 21:21  [ТС]
Я всё равно не понимаю.
Меня интересует сейчас только одна часть текущей темы: неожиданные преобразования.

Все о них говорят, но никто не показывает такую неожиданность в действии.
Я не вижу другого поведения, что я должен был ожидать? Кроме того, что можно ожидать, что программа компилироваться не должна, мне ничего в голову не приходит.

Как засветить проблему?

Кроме того, что можно сказать: "я не знаю, почему это работает", мне и сказать нечего. (если я не знаю о конвертирующем конструкторе, конечно).
0
19426 / 10042 / 2447
Регистрация: 30.01.2014
Сообщений: 17,709
29.04.2017, 22:10
Лучший ответ Сообщение было отмечено daslex как решение

Решение

Цитата Сообщение от daslex Посмотреть сообщение
Я всё равно не понимаю.
Ну я попробую последний раз с другой стороны. Если что, уж не обессудьте

Представим, что у нас есть большой С++ проект, в котором есть такой класс:
C++
1
2
3
4
5
6
7
class String
{
public:
    String(size_t count, char ch = '\0');
 
    //... остальное
};
Далее допустим, что у нас есть функции:
C++
1
2
void do_something(String const & x);
void do_something(int);
И они много раз вызываются в коде проекта. До этих пор все вроде бы хорошо.
Далее, представим, что на каком-то этапе развития проекта решили провести рефакторинг и заменить функцию
C++
1
void do_something(int);
на
C++
1
void do_something_with_int(int);
На что теперь следует обратить внимание? На то, что вызовы
C++
1
do_something(int_number);
везде по коду продолжат компилироваться без проблем. И если кто-то по каким-либо причинам не поменяет все такие вызовы на
C++
1
do_something_with_int(int_number);
,
то поведение кода изменится, и вполне возможно, что заметить это удастся уже слишком поздно.
Понятно, что пример несколько утрированный, но по сути своей обычно все именно так и происходит: что-то меняется, код продолжает компилироваться, ошибка маскируется. explicit - это средство, позволяющее переложить часть контроля за кодом на плечи компилятора, облегчив тем самым работу программиста. За этим же в С++11 добавили возможность указывать explicit в user-defined conversion operator. В его отсутствие в некоторых случаях вынуждены были выдумывать вот такие обходные костыли: safe bool idiom.
2
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
30.04.2017, 23:04  [ТС]
DrOffset, Ваш последний ответ замечателен.
Спасибо.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
30.04.2017, 23:04
Помогаю со студенческими работами здесь

Ошибка "expected constructor, destructor, or type conversion"
//ourfunc.cpp - îïðåäåëÿåò âàøó ñîáñòâåííóþ ôóíêöèþ #include &lt;iostream&gt; using namespace std; void simon(int); //ïðîòîòèï ôóíêöèè ...

Нужны пояснения
Читаю &quot;С++ руководство для начинающих&quot; Герберта Шилдта. Дочитал до &quot;передача аргументов командной строки функции main()&quot;. То ли я...

Нужны некоторые пояснения
При выполнении программы есть область 20 на 20. 1) Почему при движении вправо или влево, после того, как заканчивается строчка, курсор...

Нужны пояснения по вложенным классам
задался вот таким вопросом, почему не получается объявить вложенный класс следующим образом? #include &lt;iostream&gt; using namespace...

Синглтон Мейерса, нужны некоторые пояснения
class Singleton{ public: static Singleton&amp; init() { static Singleton Object; return Object; } ...


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

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Опции темы

Новые блоги и статьи
Batch Transform и Batch Gizmo Drawing API в Unity
GameUnited 20.04.2025
В мире разработки игр и приложений на Unity производительность всегда была критическим фактором успеха. Создатели игр постоянно балансируют между визуальной привлекательностью и плавностью работы. . .
Звук в Unity: Рандомизация с Audio Random Container
GameUnited 20.04.2025
В современных играх звуковое оформление часто становится элементом, который либо полностью погружает игрока в виртуальный мир, либо разрушает атмосферу за считанные минуты. Представьте: вы исследуете. . .
Максимальная производительность C#: Советы, тестирование и заключение
stackOverflow 20.04.2025
Погружение в мир микрооптимизаций C# открывает перед разработчиком целый арсенал мощных техник. Но как определить, где и когда их применять? Ответ начинается с точных измерений и профилирования. . . .
Максимальная производительность C#: Предсказание ветвлений
stackOverflow 20.04.2025
Третий ключевой аспект низкоуровневой оптимизации — предсказание ветвлений. Эта тема менее известна среди разработчиков, но её влияние на производительность может быть колоссальным. Чтобы понять. . .
Максимальная производительность C#: Векторизация (SIMD)
stackOverflow 20.04.2025
Помимо работы с кэшем, другим ключевым аспектом низкоуровневой оптимизации является векторизация вычислений. SIMD (Single Instruction, Multiple Data) позволяет обрабатывать несколько элементов данных. . .
Максимальная производительность C#: Процессорный кэш
stackOverflow 20.04.2025
Знакомство с внутренним устройством процессорного кэша — ключевой шаг в написании по-настоящему быстрого кода на C#. Этот слой архитектуры компьютера часто ускользает от внимания разработчиков, но. . .
Максимальная производительность C#: Введение в микрооптимизации
stackOverflow 20.04.2025
В мире разработки на C# многие привыкли полагаться на . NET Runtime, который "магическим образом" сам оптимизирует код. И часто это работает - современные JIT-компиляторы творят чудеса. Но когда речь. . .
MVC фреймворк в PHP
Jason-Webb 19.04.2025
Архитектурный паттерн Model-View-Controller (MVC) – это не просто модный термин из мира веб-разработки. Для PHP-программистов это фундаментальный подход к организации кода, который радикально меняет. . .
Dictionary Comprehensions в Python
py-thonny 19.04.2025
Python славится своей выразительностью и лаконичностью, что позволяет писать чистый и понятный код. Среди множества синтаксических конструкций языка особое место занимают словарные включения. . .
Шаблоны и протоколы для создания устойчивых микросервисов
ArchitectMsa 19.04.2025
Микросервисы — архитектурный подход, разбивающий сложные приложения на небольшие, независимые компоненты. Вместо монолитного гиганта, система превращается в созвездие небольших взаимодействующих. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru