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

объяснить функцию - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.78
Mr. Pyatachok
 Аватар для Mr. Pyatachok
8 / 8 / 0
Регистрация: 30.06.2011
Сообщений: 250
09.10.2011, 17:44     объяснить функцию #1
Всем привет!
Есть код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<conio.h>
#include<iostream.h>
 
class integer1
{
  int val;
    public:
  integer1(int v0 ) {val=v0;}
  friend integer1 INC(integer1);
  integer1 INC(integer1 scr) {scr.val++; return scr;}
 
};
 
void main()
{
 integer1 x(5),y=(0),z=(0);
 y=INC(x);
 z=INC(INC(x));
 
 getch();
}
Необходимо подсчитать количество объектов и изобразить схему их взаимодействия (копирование, отображение).

Объектов 3, помогите понять что твориться в этих строках
C++
1
2
friend integer1 INC(integer1);
integer1 INC(integer1 scr) {scr.val++; return scr;}
Заранее спасибо
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.10.2011, 17:44     объяснить функцию
Посмотрите здесь:

Объяснить программу C++
Функция (объяснить) C++
Объяснить строку C++
Объяснить прогграму C++
Объяснить код на С++ C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
aeshes
 Аватар для aeshes
437 / 200 / 13
Регистрация: 07.10.2011
Сообщений: 462
09.10.2011, 17:52     объяснить функцию #2
Не понятно, какое отношение имеет код к заданию о количестве объектов, ну ладно
1) почему строка
C++
1
integer1 INC(integer1 scr) {scr.val++; return scr;}
находится в пределах класса? Она должна быть за пределами класса

А так это объявление дружественной функции инкремента для класса и реализация этой функции.
Mr. Pyatachok
 Аватар для Mr. Pyatachok
8 / 8 / 0
Регистрация: 30.06.2011
Сообщений: 250
09.10.2011, 18:13  [ТС]     объяснить функцию #3
дело в том, что препод дал только код из книги и все

Добавлено через 15 минут
Извините, но можно поподробнее объяснить что и зачем?
Заранее благодарен
Nameless One
Эксперт С++
 Аватар для Nameless One
5753 / 3402 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
09.10.2011, 18:20     объяснить функцию #4
Цитата Сообщение от Mr. Pyatachok Посмотреть сообщение
дело в том, что препод дал только код из книги и все
плохая книга

Цитата Сообщение от Mr. Pyatachok Посмотреть сообщение
Извините, но можно поподробнее объяснить что и зачем?
вынеси определение функции INC из класса. Прочитай где-нибудь про дружественные функции. Все вопросы отпадут сами собой
-=ЮрА=-
Заблокирован
Автор FAQ
09.10.2011, 18:23     объяснить функцию #5
Цитата Сообщение от Mr. Pyatachok Посмотреть сообщение
class integer1
{
* int val;
* * public:
* integer1(int v0 ) {val=v0;}
* friend integer1 INC(integer1);
* integer1 INC(integer1 scr) {scr.val++; return scr;}
};
- объявление класса integer1 с конструктором преобразования
Цитата Сообщение от Mr. Pyatachok Посмотреть сообщение
integer1(int v0 ) {val=v0;}
и privat(закрытой переменной)
Цитата Сообщение от Mr. Pyatachok Посмотреть сообщение
int val;
Цитата Сообщение от Mr. Pyatachok Посмотреть сообщение
friend integer1 INC(integer1);
- объявление дружественной функции INC (она инкрементирует(увеличивает) privat-переменную класса integer1)

В программе это
Цитата Сообщение от Mr. Pyatachok Посмотреть сообщение
integer1 x(5),y=(0),z=(0);
- объявление 3-х перемменных класса integer1(в данном случае класс integer1 выступает как созданный нами отдельный тип данных)

Цитата Сообщение от Mr. Pyatachok Посмотреть сообщение
y=INC(x);
- переинициализируем переменную у типа integer1 через конструктор преобразования (после данного конструктора значение privat-переменной станет равным 5)

Цитата Сообщение от Mr. Pyatachok Посмотреть сообщение
z=INC(INC(x));
вызов дружественной классу integer1 функции
в качестве параметра которой вызван конструктор преобразования INC(x), в результате в private переменных z и х будет 6
Сыроежка
Заблокирован
09.10.2011, 18:32     объяснить функцию #6
Тут вам, как всегда, "грамотные" модераторы дали неверные советы.

Дружественная функция может быть определена внутри класса.

Что касается вашего вопроса про выделенные вами строки, то это задается дружественная функция INC вашего класса integer1. То есть сначала она объявляется, а затем следом внутри класса определяется. В этом случае эта функция является встраиваемой.

Друзьями класса (в том числе дружественной функцией) является функция или класс, которые не являются членами класса, для которого они определены дружественными, но при этом они могут использовать закрытые и защищенные имена членов данного класса.

То есть в вашем классе член val объявлен со спецификатором доступа private, то есть это означает , что вне класса к нему обратиться нельзя. Тем не менее класс таким правом обращения к своему закрытому члену val наделяет функцию INC. Эта функция будет иметь доступ к этому закрытому члену класса и сможет его изменять.
-=ЮрА=-
Заблокирован
Автор FAQ
09.10.2011, 18:34     объяснить функцию #7
Mr. Pyatachok, я тут немножко вам солгал, простите пожалусто!
Цитата Сообщение от Mr. Pyatachok Посмотреть сообщение
y=INC(x);
- это вызов дружественной функции
Цитата Сообщение от Mr. Pyatachok Посмотреть сообщение
friend integer1 INC(integer1);
в результате у.val переинициализируем x.val = (5++) = 6


Цитата Сообщение от Mr. Pyatachok Посмотреть сообщение
z=INC(INC(x));
- это тот же вызов френд функции, причём сразу 2-жды z.val = ((6++)++) = 8!
aeshes
 Аватар для aeshes
437 / 200 / 13
Регистрация: 07.10.2011
Сообщений: 462
09.10.2011, 18:41     объяснить функцию #8
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
y=INC(x);
- переинициализируем переменную у типа integer1 через конструктор преобразования (после данного конструктора значение privat-переменной станет равным 5)
Разве здесь вызывается конструктор преобразования? здесь у присваивается результат работы функции. Работать должен конструктор копий, созданный компилятором по умолчанию, или операция присваивания, опять же созданная компилятором по умолчанию. Поправьте, если ошибаюсь

Результаты работы программы в VS2010
x y z
5 0 0
5 6 0
5 6 7

Мне VS2010 на попытку написания тела дружественной функции в теле класса после прототипа выдала ошибку линковки. хотя если неписать прототип, а сделать сразу
C++
1
  friend integer1 INC(integer1 scr) {scr.val++; return scr;}
то все работает
Сыроежка
Заблокирован
09.10.2011, 18:45     объяснить функцию #9
Кстати сказать, в С++ функция main должна иметь тип возвращаемого значения int, а не void, как у вас написано. То есть должно быть объявление

C++
1
int main()
В крайнем случае, если вам лень писать int, вы можете написать просто

C++
1
main()
так как в С++ действует правило умолчания, для возвращаемых значений функций (по крайней мере в Стандарте С++ 2003 года), то есть если вы не указываете тип возвращаемого значения, то предполагается, что он имеет тип int

Кроме того заголовок iostream следует писать без расширения .h, то есть в виде

C++
1
#include   <iostream>
Добавлено через 3 минуты
Цитата Сообщение от aeshes Посмотреть сообщение
Разве здесь вызывается конструктор преобразования? здесь у присваивается результат работы функции. Работать должен конструктор копий, созданный компилятором по умолчанию, или операция присваивания, опять же созданная компилятором по умолчанию. Поправьте, если ошибаюсь

Результаты работы программы в VS2010
x y z
5 0 0
5 6 0
5 6 7

Мне VS2010 на попытку написания тела дружественной функции в теле класса выдала ошибку линковки. Может, тут конечно имеет место быть несоответствие компилятора стандартам, но все же...
Любой конструктор с одним параметром или с несколькими параметрами, когда остальные параметры кроме первого имеют аргументы по умолчанию, в том числе и конструктор копирования, называются определенными пользователем функциями преобразования.

Что касается ошибки линковки, то у Майкрософт VC++ здесь имеется баг. Более того этот баг присутствует и в VC++ 2010. В VC 2010 вообще куча багов! Пример самого простого мною найденного бага

C++
1
2
3
4
struct A
{
  int A;
};

Данный совершенно корректный код на VC 2010 не компилируется! Правда это относится к компилятору без SP1. С SP1 я не проверял, исправили они ошибку или нет.
aeshes
 Аватар для aeshes
437 / 200 / 13
Регистрация: 07.10.2011
Сообщений: 462
09.10.2011, 18:49     объяснить функцию #10
Цитата Сообщение от Сыроежка Посмотреть сообщение
Любой конструктор в том числе и конструктор копирования, называются определенными пользователем функциями преобразования.
Но тут-то как раз не было определено конструктора копий, а значит, мы не можем назвать его определенными пользователем функциями преобразования. Для меня здесь один конструктор, объявленный пользователем, он же конструктор преобразования из int в integer1. И он там не вызвался. Возможно, плохо владею терминологией

Цитата Сообщение от Сыроежка Посмотреть сообщение
struct A
{
int A;
};
А так можно? я не знала
Nameless One
Эксперт С++
 Аватар для Nameless One
5753 / 3402 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
09.10.2011, 18:52     объяснить функцию #11
Цитата Сообщение от Сыроежка Посмотреть сообщение
Дружественная функция может быть определена внутри класса.
а в чем тогда тут проблема?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<iostream>
 
class integer1
{
  int val;
    public:
  integer1(int v0 ) {val=v0;}
  friend integer1 INC(integer1);
  integer1 INC(integer1 scr) {scr.val++; return scr;}
 
};
 
int main()
{
 integer1 x(5),y=(0),z=(0);
 y=INC(x);
 z=INC(INC(x));
}
Код
-*- mode: compilation; default-directory: "/home/nameless/samples/cpp/" -*-
Compilation started at Mon Oct 10 01:48:30

make -j8
g++ -c -Wall -g -std=c++0x main.cc
g++ -o sample  main.o
main.o: In function `main':
/home/nameless/samples/cpp/main.cc:16: undefined reference to `INC(integer1)'
/home/nameless/samples/cpp/main.cc:17: undefined reference to `INC(integer1)'
/home/nameless/samples/cpp/main.cc:17: undefined reference to `INC(integer1)'
collect2: выполнение ld завершилось с кодом возврата 1
make: *** [sample] Ошибка 1

Compilation exited abnormally with code 2 at Mon Oct 10 01:48:31
Цитата Сообщение от Сыроежка Посмотреть сообщение
Что касается ошибки линковки, то у Майкрософт VC++ здесь имеется баг.
и у gcc тоже баг, да?
Код
[nameless@desktop ~]$ gcc --version
gcc (GCC) 4.6.1 20110908 (Red Hat 4.6.1-9)
aeshes
 Аватар для aeshes
437 / 200 / 13
Регистрация: 07.10.2011
Сообщений: 462
09.10.2011, 18:53     объяснить функцию #12
Nameless One, подозреваю, что если в теле класса поместить определение дружественной функции без прототипа, то должно все работать. а вот если и прототип. и потом реализация - то нет
Сыроежка
Заблокирован
09.10.2011, 18:58     объяснить функцию #13
Цитата Сообщение от aeshes Посмотреть сообщение
Но тут-то как раз не было определено конструктора копий, а значит, мы не можем назвать его определенными пользователем функциями преобразования. Для меня здесь один конструктор, объявленный пользователем, он же конструктор преобразования из int в integer1. И он там не вызвался. Возможно, плохо владею терминологией



А так можно? я не знала
Это не имеет значения, сами мы определили конструктор копирования, или он для нас создан компилятором по умолчанию. Важно, что имеется один параметр.

Что касается примера со структурой, то это совершенно корректный код, если в определении структуры не объявлен конструктор. Дело в том, что в языке С, с которым С++ желательно должен быть максимально совместим, имя структуры и имена переменных, ее членов, находятся в разных пространствах имен. Если считать предложенную конструкцию некорректной, то тогда огромное число кода, написанного на С, будет не компилироваться на С++.
Mr. Pyatachok
 Аватар для Mr. Pyatachok
8 / 8 / 0
Регистрация: 30.06.2011
Сообщений: 250
09.10.2011, 19:04  [ТС]     объяснить функцию #14
Извините за наглость, но можете еще прокомментировать еще один код и я отстану со своими нубскими вопрсами
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>
#include<conio.h>
#include<stdio.h>
class string1
{
  char *s;
    public:
  string1(char *);
  string1(string1 &);
  string1();
  char operator[](int n)
  { if(n>=strlen(s))return(' ');return(s[n]); }
};
 
void main()
{
  char c,t;
  string1 x("abcd");
  c=x[2];
  t=x[20];
 
 getch();
}
Объясните что и как работает пожалуйста, а то я в ступоре
Сыроежка
Заблокирован
09.10.2011, 19:07     объяснить функцию #15
Цитата Сообщение от Nameless One Посмотреть сообщение
а в чем тогда тут проблема?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<iostream>
 
class integer1
{
  int val;
    public:
  integer1(int v0 ) {val=v0;}
  friend integer1 INC(integer1);
  integer1 INC(integer1 scr) {scr.val++; return scr;}
 
};
 
int main()
{
 integer1 x(5),y=(0),z=(0);
 y=INC(x);
 z=INC(INC(x));
}
Код
-*- mode: compilation; default-directory: "/home/nameless/samples/cpp/" -*-
Compilation started at Mon Oct 10 01:48:30

make -j8
g++ -c -Wall -g -std=c++0x main.cc
g++ -o sample  main.o
main.o: In function `main':
/home/nameless/samples/cpp/main.cc:16: undefined reference to `INC(integer1)'
/home/nameless/samples/cpp/main.cc:17: undefined reference to `INC(integer1)'
/home/nameless/samples/cpp/main.cc:17: undefined reference to `INC(integer1)'
collect2: выполнение ld завершилось с кодом возврата 1
make: *** [sample] Ошибка 1

Compilation exited abnormally with code 2 at Mon Oct 10 01:48:31
и у gcc тоже баг, да?
Код
[nameless@desktop ~]$ gcc --version
gcc (GCC) 4.6.1 20110908 (Red Hat 4.6.1-9)
Вполне возможно, что у обоих компиляторов имеется данный баг. Здесь проблема связана с тем, что в классе одновременно присутствует объявление и определение дружественной функции. Скорей всего компилятор gcc разделяет эти две функции. То есть проблема заключается в том, что функция, впервые объявленная в виде дружественной в классе, имеет внешнее связывание. Тогда как функции, являющиеся встраиваемыми, имеют внутреннее связывание. Когда одно и тоже имя определено как имеющее внешнее связывание и внутреннее связывание, то поведение не определенное.
Попробуйте убрать из класса объявление функцуии и оставьте только определение и прокомпилируйте с помощью gcc. Мне самому будет интересен результат.

Чтобы сомнений не было, я процитирую стандарт, раздел 11.4 "Friends" #5. "A function can be defined in a friend declaration of a class if and only if the class is a non-local class"
Nameless One
Эксперт С++
 Аватар для Nameless One
5753 / 3402 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
09.10.2011, 19:10     объяснить функцию #16
Mr. Pyatachok, там не на что смотреть, кроме как на реализацию оператора доступа по индексу. Он возвращает символ пробела, если переданный индекс больше либо равен размеру хранимой строки, и соответствующий символ строки. И да, в 20 строке мы выйдем за границы массива. Ну или если передадим отрицательный индекс.
Сыроежка
Заблокирован
09.10.2011, 19:11     объяснить функцию #17
Цитата Сообщение от Mr. Pyatachok Посмотреть сообщение
Извините за наглость, но можете еще прокомментировать еще один код и я отстану со своими нубскими вопрсами
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>
#include<conio.h>
#include<stdio.h>
class string1
{
  char *s;
    public:
  string1(char *);
  string1(string1 &);
  string1();
  char operator[](int n)
  { if(n>=strlen(s))return(' ');return(s[n]); }
};
 
void main()
{
  char c,t;
  string1 x("abcd");
  c=x[2];
  t=x[20];
 
 getch();
}
Объясните что и как работает пожалуйста, а то я в ступоре
Здесь у вас ничего работать не будет, так как нет определений конструкторов класса. А так у вас определен класс, который имеет три конструктора, включая конструктор копирования, и оператор [], который возвращает символ строки по заданному индексу, либо символ пробела, если индекс превосходит или равен длине строки.
Nameless One
Эксперт С++
 Аватар для Nameless One
5753 / 3402 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
09.10.2011, 19:14     объяснить функцию #18
Цитата Сообщение от Сыроежка Посмотреть сообщение
Попробуйте убрать из класса объявление функцуии и оставьте только определение и прокомпилируйте с помощью gcc. Мне самому будет интересен результат.
с friend integer1 INC(integer1 scr) {scr.val++; return scr;} все нормально компилируется. Видимо, это и имеется в виду под "definition in a friend declaration". Просто выглядит довольно сомнительным, что у двух самых популярных компиляторов имеется один и тот же баг

Mr. Pyatachok, где ты такой код берешь?
Mr. Pyatachok
 Аватар для Mr. Pyatachok
8 / 8 / 0
Регистрация: 30.06.2011
Сообщений: 250
09.10.2011, 19:17  [ТС]     объяснить функцию #19
Извините но книгу препод не показал.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.10.2011, 19:19     объяснить функцию
Еще ссылки по теме:

C++ Объяснить задание
Объяснить выражение C++
C++ Объяснить функцию проверки степени

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

Или воспользуйтесь поиском по форуму:
Сыроежка
Заблокирован
09.10.2011, 19:19     объяснить функцию #20
Цитата Сообщение от Nameless One Посмотреть сообщение
с friend integer1 INC(integer1 scr) {scr.val++; return scr;} все нормально компилируется. Видимо, это и имеется в виду под "definition in a friend declaration". Просто выглядит довольно сомнительным, что у двух самых популярных компиляторов имеется один и тот же баг

Mr. Pyatachok, где ты такой код берешь?
Правильно ли я понял, что вы проверили использование определения этой дружественной функции внутри класса, убрав из класса предварительное ее объявление, и у вас с помощью gcc все скомпилировалось? Если это так, то объяснение, как я уже указал, кроется в том, что gcc рассматривал эти два объявления (предварительное объявление и определение), как две различные функции, так как они имеют разное связывание: внешнее и внутреннее.

Что касается Майкрософт VC++ 2010, то, даже убрав из класса предварительное объявление, код не компилируется. То есть имеет место очевидный баг. Например, на старом Borland Builder 5.0 этот код компилируется.
Yandex
Объявления
09.10.2011, 19:19     объяснить функцию
Ответ Создать тему
Опции темы

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