Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 5.00/11: Рейтинг темы: голосов - 11, средняя оценка - 5.00
0 / 0 / 0
Регистрация: 10.08.2015
Сообщений: 6
1

Почему после конструктора первого класса стоит двоеточие и имя переменной, а не инициализация?

10.08.2015, 19:23. Показов 2155. Ответов 30
Метки нет (Все метки)

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
#include <iostream>
template <typename T> class first
{
public:
    T value;
    first (T n) : value(n) {}
    virtual first<T>& operator* (T n) { value*=n; return *this; }
    virtual first<T>& operator+ (T n) { value+=n; return *this; }
};
template <typename T> std::ostream& operator<< (std::ostream& str, const first<T>& obj)
{
    return str << obj.value;
}
template <typename T> class second: public first<T>
{
public:
    second (T n) : first<T>(n>>3) {}
    second& operator* (T n) { first<T>::value*=n/3; return *this; }
    second& operator+ (T n) { first<T>::value+=n&3; return *this; }
};
int main ()
{
    second<unsigned> obj(5);
    first<unsigned>* ptr = &obj;
    std::cout << *ptr *25+25 << std::endl;
}
Уважаемые люди, подскажите почему после конструктора первого класса стоит двоеточие и имя переменной, а не инициализация?

И в перегрузке операторов во втором классе такое интерестное обращение, почему не first.value = n/3?
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
10.08.2015, 19:23
Ответы с готовыми решениями:

Инициализация шаблонного класса(В конструкторе класса после двоеточия вновь имя класса)
Всем доброго времени суток! Пытаюсь разобраться как работает приведенный мной код. Конкретно,...

Инициализация конструктора и конструктора родительского класса
Есть два класса: class C1 { public $a; public $b; public $c; function...

Инициализация конструктора класса
инициализация конструктора класса Rectangle::Rectangle(int w, int h): itsWidth(w),...

Инициализация конструктора базового класса
class animal { public: animal(int a):ianimal(a){} protected: int ianimal; }; ...

30
Эксперт С++
4974 / 3081 / 456
Регистрация: 10.11.2010
Сообщений: 11,160
Записей в блоге: 10
10.08.2015, 19:50 2
Цитата Сообщение от Panwo Посмотреть сообщение
почему после конструктора первого класса стоит двоеточие и имя переменной, а не инициализация?
Так это и есть инициализация. Называется список инициализации конструктора.

Цитата Сообщение от Panwo Посмотреть сообщение
почему не first.value = n/3?
Потому что базовый класс шаблонный, поэтому необходимо указать параметр шаблона.
0
Заблокирован
10.08.2015, 19:52 3
Panwo, двоеточие означает раскрытие области видимости,его наличие в коде обусловлено желанием дизайнера класса получить доступ к конкретному полу класса родителя(часто поля перегружены и прямой доступ по имени к полю в базовом классе невозможен)
Привожу простой пример с перегруженным параметром int param в двух классах
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
#include <iostream>
using namespace std;
 
class cFirst{
protected:
    int param;
public:
    cFirst(){
        param = 1;
    }
    int data(){
        return param;
    }
};
 
class cSecond : public cFirst{
protected:
    int param;
public:
      cSecond(){
        param = 2;
    }
    int data(){
        return param + cFirst::param;
    }
};
 
int main(){
    cSecond test;
    cout<<test.data()<<endl;
    return 0;
}
int data(){
return param + cFirst:aram;
}
- в данной точке кода без раскрытия области видимости я бы не смог обратиться к полу param d классе cFirst
http://codepad.org/TbhrJ00Y
0
Заблокирован
10.08.2015, 19:58 4
Цитата Сообщение от Panwo Посмотреть сообщение
second (T n) : first<T>(n>>3) {}
- здесь же одно двоеточие означает список инициализации
Цитата Сообщение от Panwo Посмотреть сообщение
first (T n) : value(n) {}
- целиком эквиваленто записи
C++
1
first (T n) { value = n;}
0
528 / 430 / 159
Регистрация: 25.11.2014
Сообщений: 1,662
10.08.2015, 20:08 5
Цитата Сообщение от ОгУрЕц Посмотреть сообщение
- целиком эквиваленто записи
Код C++Выделить код
1
first (T n) { value = n;}
Это не так. В случае со списком инициализации объект конструируется сразу с переданным значением. А в представленном тобой случае вызовется конструктор по умолчанию для T при создании объекта, а потом еще и инициализация.
0
Заблокирован
10.08.2015, 20:20 6
Velesthau, я написал эквивалентно (это не == на 100%), далее отмечу, что современный стандарт С++ предполагает от компилятора довольно серьёзную оптимизацию именно в рамках стандарта(есть много вкусностей к примеру copy elision), так что для указанного мной примера с оптимизацией от компилятора асм дял кода с конструктором будет идентичен коду со списком инициализации, ровно также как будет идентичен асм для префиксного и постфиксного инкримента в for-e
0
Эксперт С++
4974 / 3081 / 456
Регистрация: 10.11.2010
Сообщений: 11,160
Записей в блоге: 10
10.08.2015, 20:32 7
Цитата Сообщение от ОгУрЕц Посмотреть сообщение
я написал эквивалентно (это не == на 100%)
Разве?
0
Эксперт С++
8429 / 4101 / 895
Регистрация: 15.11.2014
Сообщений: 9,214
10.08.2015, 20:38 8
Цитата Сообщение от ОгУрЕц Посмотреть сообщение
- целиком эквиваленто записи
first (T n) { value = n;}
неверно.

инициализация исполняется в списках инициализации.

в теле конструктора исполняется присвоение
для уже созданного и проинициализированного объекта.

это - принципиально.

например,
если у класса оператор= окажется под запретом,
код в принципе не скомпилируется,
и никакие оптимизации его не спасут.

Цитата Сообщение от ОгУрЕц Посмотреть сообщение
к примеру copy elision
это - не принципиально.

принципиально понимать суть происходящего согласно правилам языка.

что касается оптимизаций, то здесь важно понимать,
что компилятор сначала проверяет синтаксис,
и только потом оптимизирует:

http://rextester.com/NKKFI22876

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
 
struct example
{
    example(int v) 
        { std::cout<<"ctor with params\n"; }
    
private:
    example(const example& )
        { std::cout<<"copy ctor\n"; }
    
};
 
int main()
{
    std::cout << "Hello, world!\n";
    
    // error: ‘example::example(const example&)’ is private
    example ex = 10;
}
в этом примере должен сработать copy elision
после чего, конструктор копии становится ненаблюдаемым.

однако прежде, компилятор выполняет проверку синтаксиса,
и видет, что запуск конструктора копии запрещен.
на что и ругается.

если закомментировать модификатор private:
тогда проверка синтаксиса пройдет успешно,
и компилятор действительно оптимизирует конструктор копии.


кстати, все это не имеет никакого отношения к теме:
"что есть инициализация, а что - присвоение"
0
528 / 430 / 159
Регистрация: 25.11.2014
Сообщений: 1,662
10.08.2015, 20:47 9
Цитата Сообщение от ОгУрЕц Посмотреть сообщение
так что для указанного мной примера с оптимизацией от компилятора асм дял кода с конструктором будет идентичен коду со списком инициализации
Да ну? И ничего, что я могу переопределить оператор= для T и компилятор будет обязан его вызвать. А чтобы вызвать, нужен уже сконструированный объект. Ему деваться некуда, он будет звать конструктор по умолчанию у value перед тем, как дойдет до value = n;

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

Не по теме:

hoggy, не видел, что ты уже написал про оператор=.

0
6992 / 6030 / 2738
Регистрация: 14.04.2014
Сообщений: 25,792
10.08.2015, 20:52 10
Ну а если T - целое? Судя по всему так и предполагается у автора. Тогда будет одно и то же хоть со списком, хоть с присваиванием.
0
Заблокирован
10.08.2015, 21:00 11
Цитата Сообщение от Velesthau Посмотреть сообщение
Да ну? И ничего, что я могу переопределить оператор= для T и компилятор будет обязан его вызвать. А чтобы вызвать, нужен уже сконструированный объект. Ему деваться некуда, он будет звать конструктор по умолчанию у value перед тем, как дойдет до value = n;
Цитата Сообщение от hoggy Посмотреть сообщение
неверно.
инициализация исполняется в списках инициализации.
- открываем дизасемблер и смотрим соптимизированный компиллером в стандарте код , потом пишем.
Assembler
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
26:   int main(){
00401580   push        ebp
00401581   mov         ebp,esp
00401583   sub         esp,48h
00401586   push        ebx
00401587   push        esi
00401588   push        edi
00401589   lea         edi,[ebp-48h]
0040158C   mov         ecx,12h
00401591   mov         eax,0CCCCCCCCh
00401596   rep stos    dword ptr [edi]
27:       cOne one;
00401598   lea         ecx,[ebp-4]
0040159B   call        @ILT+475(cOne::cOne) (004011e0)
28:       cTwo two;
004015A0   lea         ecx,[ebp-8]
004015A3   call        @ILT+405(cTwo::cTwo) (0040119a)
29:       cout<<one.data()<<endl;
004015A8   push        offset @ILT+200(std::endl) (004010cd)
004015AD   lea         ecx,[ebp-4]
004015B0   call        @ILT+580(cOne::data) (00401249)
004015B5   push        eax
004015B6   mov         ecx,offset std::cout (004767e0)
004015BB   call        @ILT+255(std::basic_ostream<char,std::char_traits<char> >::operator<<) (00401104)
004015C0   mov         ecx,eax
004015C2   call        @ILT+490(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011ef)
30:       cout<<two.data()<<endl;
004015C7   push        offset @ILT+200(std::endl) (004010cd)
004015CC   lea         ecx,[ebp-8]
004015CF   call        @ILT+145(cTwo::data) (00401096)
004015D4   push        eax
004015D5   mov         ecx,offset std::cout (004767e0)
004015DA   call        @ILT+255(std::basic_ostream<char,std::char_traits<char> >::operator<<) (00401104)
004015DF   mov         ecx,eax
004015E1   call        @ILT+490(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011ef)
31:       return 0;
004015E6   xor         eax,eax
32:   }
Ещё раз я нигде не сказал что список инициализации 100% == вызову конструтора, но для данного случая
Цитата Сообщение от ОгУрЕц Посмотреть сообщение
целиком эквиваленто записи
Код C++Выделить код
1
first (T n) { value = n;}
- это так и есть.
Асм подан для данного кода.
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
#include <iostream>
using namespace std;
 
class cOne{
protected:
    int param;
public:
    cOne(){
        param = 0;
    }
    int data(){
        return param;
    }
};
 
class cTwo{
protected:
    int param;
public:
    cTwo() : param(0) {}
    int data(){
        return param;
    }
};
 
int main(){
    cOne one;
    cTwo two;
    cout<<one.data()<<endl;
    cout<<two.data()<<endl;
    return 0;
}
http://codepad.org/ZVD2NZbb
Цитата Сообщение от hoggy Посмотреть сообщение
struct example
{
* * example(int v)
* * * * { std::cout<<"ctor with params\n"; }
private:
* * example(const example& )
* * * * { std::cout<<"copy ctor\n"; }
};
- это вообще хрень на постном масле, ты взял запихнул конструктор копирования в приват и говоришь о copy elision - вообще знаешь что это copy elision?Твой код говорит что нет, извини

Не по теме:

PS:А где о copy elision говорится в стандарте напишешь?С нетерпением жду ответ.



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

Не по теме:

Цитата Сообщение от nmcf Посмотреть сообщение
Ну а если T - целое? Судя по всему так и предполагается у автора. Тогда будет одно и то же хоть со списком, хоть с присваиванием.
- вот это уже здравая мысль!(я одобрямс;))

0
Эксперт С++
8429 / 4101 / 895
Регистрация: 15.11.2014
Сообщений: 9,214
10.08.2015, 21:03 12
Цитата Сообщение от ОгУрЕц Посмотреть сообщение
открываем дизасемблер и смотри соптимизированный компиллером код в стандарте, потом пишим
меня не интересует ассм.
который в зависимости от, может быть самым разным.

меня интересует с++

человек который ставит знак равенства
между присвоением и инициализацией демонстрирует не знание основ языка.

Цитата Сообщение от ОгУрЕц Посмотреть сообщение
это вообще хрень на постном масле взял запихнул конструктор копирования в приват и говоришь о copy elision - вообще знаешь что это copy elision?Твой код говорит что нет, извини.
я знаю, что такое copy elision.

к сожалению, до вас не дошел смысл примера-иллюстрации.
0
castaway
10.08.2015, 21:03
  #13

Не по теме:

Цитата Сообщение от ОгУрЕц Посмотреть сообщение
это вообще хрень на постном масле
Ты только что приговорил себя к длительному диалогу, в результате которого доказать свою правду тебе будет практически невозможно...

0
ОгУрЕц
10.08.2015, 21:04
  #14

Не по теме:

Цитата Сообщение от hoggy Посмотреть сообщение
меня не интересует ассм.
который в зависимости от, может быть самым разным.
меня интересует с++
- тогда открой стандарт и почтиай.
Цитата Сообщение от hoggy Посмотреть сообщение
я знаю, что такое copy elision.
- я уже увидел всё что хотел...

0
Эксперт С++
8429 / 4101 / 895
Регистрация: 15.11.2014
Сообщений: 9,214
10.08.2015, 21:05 15
Цитата Сообщение от ОгУрЕц Посмотреть сообщение
но для данного случая
в данном случае имеет место быть шаблон.
а это значит, что T может оказаться каким угодно.

в том числе тип данных,
для которого оператор= запрещен, например.

именно для шаблонов особенно критично понимание что есть что в коде.
0
Заблокирован
10.08.2015, 21:06 16
Цитата Сообщение от hoggy Посмотреть сообщение
меня интересует с++
- также открою тайну - программа будет производить действия по асму, а не по высокоуровневому коду. Я и написал о copy elision чтобы было понимание того факта, что язык допускает действия компилятора несколько противоречащие обычному порядку дел.
0
Эксперт С++
8429 / 4101 / 895
Регистрация: 15.11.2014
Сообщений: 9,214
10.08.2015, 21:09 17
Цитата Сообщение от ОгУрЕц Посмотреть сообщение
тогда октрой стандарт и почтиай
вам бы самому не помешало.
учитывая, какой бред вы порой начинаете нести.

Цитата Сообщение от ОгУрЕц Посмотреть сообщение
я уже увидел
сомневаюсь, учитывая,
что до вас так и не дошел смысл этого примера-иллюстрации.

Добавлено через 1 минуту
Цитата Сообщение от ОгУрЕц Посмотреть сообщение
также открою тайну - программа будет производить действия по асму, а не по высокоуровневому коду
почему ж тогда сразу, не машиные коды и центральный процессор?

избавьте меня пожалуйста от подобной демагогии.
мне это не интересно.
0
Заблокирован
10.08.2015, 21:11 18
Цитата Сообщение от hoggy Посмотреть сообщение
что до вас так и не дошел смысл этого примера-иллюстрации.
- а я сомневаюсь, что до вас дошёл смысл моих слов.
Цитата Сообщение от hoggy Посмотреть сообщение
в данном случае имеет место быть шаблон.
а это значит, что T может оказаться каким угодно.
- мое утверждения с интом - истинно, copy elision имеет как раз таки непосредственное отношение(см текст выше)

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

Не по теме:

Цитата Сообщение от hoggy Посмотреть сообщение
избавьте меня пожалуйста от подобной демагогии.
мне это не интересно.
- ну так это не я прибежал в тему с плохим знанием оптимизации, но большим желанием потролить якобы новичка, но как говорится "нашла коса на кемень" не так ли?

0
528 / 430 / 159
Регистрация: 25.11.2014
Сообщений: 1,662
10.08.2015, 21:14 19
ОгУрЕц, у тебя неправильный пример. У пользователя T не определен, это шаблон. Замени свой int для param на класс, в котором конструктор по умолчанию с печатью и конструктор от чего-либо с печатью. Оптимизация тут вообще не при чем.
0
Эксперт С++
4974 / 3081 / 456
Регистрация: 10.11.2010
Сообщений: 11,160
Записей в блоге: 10
10.08.2015, 21:16 20
ОгУрЕц, увы, но ты не прав (такое бывает). То что у тебя "эквиваленто" в 5-м сообщении на самом деле таковым не является, и оптимизация компилятора тут не при чём.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
10.08.2015, 21:16

Почему не компилируется код в котором описание класса стоит после main
Изучаю с++ по книге за 21 день. Почему когда я пишу так, то не компилируется: #include...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.