Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.55/55: Рейтинг темы: голосов - 55, средняя оценка - 4.55
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30

[Задача] Объясните результат исполнения программы

10.10.2011, 18:04. Показов 11937. Ответов 21

Студворк — интернет-сервис помощи студентам
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Файл t1.cc
#include <iostream>
 
class C
{
    int x;
 
  public:
    C() { x = 10; }
    int get() { return x; }
};
 
int main (void)
{
  C c;
 
  std::cout << c.get() << std::endl;
  return 0;
}
C++
1
2
3
4
5
6
7
8
9
10
11
// Файл t2.cc
class C
{
  public:
    int get();
};
 
int C::get()
{
  return 20;
}
Code
1
2
3
$ g++ t1.cc t2.cc
$ ./a.out
20
Задача из разряда "трудноуловимые ошибки"
7
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
10.10.2011, 18:04
Ответы с готовыми решениями:

Объясните результат работы следующей программы
double x =1.23456789; for(int i=0; i&lt;1030;i++) x=x/2; for( int i=0; i &lt;1030;i++) x=x*2; cout.precision (12); ...

Объясните пожалуйста результат работы программы
#include &lt;iostream&gt; using namespace std; int main() { short int i; short unsigned int j; j = 60000; ...

Как вывести результат исполнения этой программы?
Написал программу, она работает проверял в turbo debbuger. Но не могу понять как вывести результат исполнения этой программы. Помогите...

21
 Аватар для aeshes
448 / 211 / 21
Регистрация: 07.10.2011
Сообщений: 462
10.10.2011, 18:13
а если порядок файлов в строке
g++ t1.cc t2.cc
поменять?
0
186 / 186 / 21
Регистрация: 08.01.2011
Сообщений: 1,139
10.10.2011, 18:35
В Visual studio 2008 ошибка компиляции. Два раза написан метод get.
Или я не понял о чем вы?
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
 Аватар для easybudda
12843 / 7592 / 1766
Регистрация: 25.07.2009
Сообщений: 13,973
10.10.2011, 19:21
Evg, и действительно, как это оно у Вас вообще скомпилировалось?
Code
1
2
3
4
5
6
$ g++ -o t t1.cc t2.cc
/cygdrive/c/DOCUME~1/andrew/LOCALS~1/Temp/ccPKWOoS.o:t2.cc:(.text+0x0): multiple
 definition of `C::get()'
/cygdrive/c/DOCUME~1/andrew/LOCALS~1/Temp/cct23V89.o:t1.cc:(.text$_ZN1C3getEv[C:
:get()]+0x0): first defined here
collect2: ld returned 1 exit status
0
Временно недоступен
 Аватар для #pragma
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
10.10.2011, 19:28
У меня тоже всё компилируется, и тоже выводит 20
Забавно. Причем если main перенести в другую единицу трансляции, ничего не меняется.
И ещё вот параллельно возник такой вопрос (меняем только t1.сс:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Файл t1.cc
#include <iostream>
 
class C
{
    int x;
 
  public:
    C() { x = 10; }
    int get() { return x; }
};
 
int main (void)
{
  C c();
 
  std::cout << c.get() << std::endl;
  return 0;
}
Почему-то выдаёт ошибку error: request for member ‘get’ in ‘c’, which is of non-class type ‘C()’
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
 Аватар для easybudda
12843 / 7592 / 1766
Регистрация: 25.07.2009
Сообщений: 13,973
10.10.2011, 19:36
Цитата Сообщение от #pragma Посмотреть сообщение
Забавно
Ага... На бсде тоже скомпилировалось и тоже 20 вывело...
Code
1
2
3
[andrew@server2 ~/bin]$ g++ -o t t1.cc t2.cc
[andrew@server2 ~/bin]$ ./t
20
Загадка...
0
Временно недоступен
 Аватар для #pragma
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
10.10.2011, 19:51
Странно, когда перенёс x в public, один раз таки выдало 10...
Такое ощущение, что при вызове c.get() вызывается конструктор объекта класса из t2.cc
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
10.10.2011, 20:27  [ТС]
Лучший ответ Сообщение было отмечено как решение

Решение

Цитата Сообщение от aeshes Посмотреть сообщение
а если порядок файлов в строке
g++ t1.cc t2.cc
поменять?
От порядка не зависит

Цитата Сообщение от Chelioss Посмотреть сообщение
В Visual studio 2008 ошибка компиляции. Два раза написан метод get.
Или я не понял о чем вы?
Это implementation-dependend фича. Точнее, с точки зрения стандарта в тесте undefined behaviour, но как оно себя проявит - зависит от технических особенностей компилятора. Конкретно в данном случае в linux'е используется бинарный формат elf, а потому компилятор настроен одним образом. В винде используется более допотопный формат файла, из-за которого компиляторы настраиваются по другому

Цитата Сообщение от easybudda Посмотреть сообщение
Evg, и действительно, как это оно у Вас вообще скомпилировалось?
В твоём случае тоже винда

Добавлено через 3 минуты
Тест представляет собой сокращённый тестовый пример, об который конкретно споткнулись в реальной жизни: в программу локально включили описание класса, имя которого (и имя метода), как оказалось, совпало с уже существующим, но продвинутый gcc оказался бессилен с точки зрения диагностики ошибки. Вероятность таким образом вляпаться не такая уж и большая, но, как показала практика, она отлична от нуля

Добавлено через 7 минут
Упрощённый вариант двух файлов с той же выдачей:

C++
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
 
inline int func (void)
{
  return 10;
}
 
int main (void)
{
  std::cout << func() << std::endl;
  return 0;
}
C++
1
2
3
4
int func (void)
{
  return 20;
}
3
237 / 210 / 29
Регистрация: 08.06.2011
Сообщений: 467
10.10.2011, 20:39
Цитата Сообщение от #pragma Посмотреть сообщение
Почему-то выдаёт ошибку error: request for member ‘get’ in ‘c’, which is of non-class type ‘C()’
компилятор определяет
C++
1
C c();
как прототип функции, которая принимает void и возвращает объект типа C
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
11.10.2011, 10:43  [ТС]
Лучший ответ Сообщение было отмечено как решение

Решение

объяснение
Всё растёт из того, что стандарт Си++ требует того, чтобы inline-функции были multiply defined. Об этом я пояснял в Зачем нужен inline посты 6 и 11. Метод функции, описанный внутри тела класса, всегда является inline, даже если явно это не написано. gcc под системами с поддержкой elf'а реализует это свойство через weak-символы. В данном примере в первом файле мы имеем метод или функцию, определённую как weak, а во втором файле - метод или функцию с тем же манглированным именем, но уже честный global. Итого на линковке получается, что при разрешении ссылок global всегда перебивает weak

С нуля понять что такое weak несколько сложно, в своё время пояснял на более-менее живом примере: https://www.cyberforum.ru/cpp-... 46472.html


Добавлено через 5 минут
Как-то сумбурно пояснил, но для доходчивого пояснения надо рассказать про слишком многие вещи

Добавлено через 4 минуты
В догонку к пояснению
gcc через примерно такой же способ реализует шаблоны. Все шаблонные функции и переменные являются weak'ами, а потому когда они цепляются из инклюдов, то в каждом модуле получается функция с одним и тем же именем. Но за счёт weak'а на линковке отбрасывается всё, кроме одного экземпляра. А вот если есть специализация, то она строится как global, а потому перебивает все weak'и. И две специализации уже сделать нельзя, потому как два global'а уже конфликтуют друг с другом


Добавлено через 10 часов 25 минут
Совсем забыл, что про inline я уже как-то рассказывал. См. Неочевидные ответы на простые вопросы раздел 7.2
14
Заблокирован
18.11.2011, 06:16
Что-то уж очень противоречивое.
А как все это согласуется с тем, что любой объект в программе может быть определен только один раз.
Здесь явно это правило нарушено.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
22.11.2011, 13:38  [ТС]
Цитата Сообщение от thick_int Посмотреть сообщение
Что-то уж очень противоречивое.
А как все это согласуется с тем, что любой объект в программе может быть определен только один раз.
Здесь явно это правило нарушено.
Объект определён ровно один раз. А два раза определён метод. Если ты два раза напишешь функцию на Си, то у тебя поломается на линковке. А здесь исходник содержит ошибку, но на линковке ошибка не проявилась. Так вот устроен язык Си++, что некоторые из реалиаций языка оказываются ненадёжными в этом плане. Потому что придумать язык мало, надо ещё и понимать, как будет работать компилятор с него и какие при этом могут оказаться подводные камни
0
Заблокирован
22.11.2011, 18:22
Ну уж не знаю, каким Вы компилятором пользуетесь, но я все таки не поленился перекопировал код Вашей так называемой ошибки и вот, что выдает VS2010

Ошибка 1 error LNK2005: "public: int __thiscall C::get(void)" (?get@C@@QAEHXZ) уже определен в c22.obj c:\Users\...\documents\visual studio 2010\Projects\ErrProj\ErrProj\ErrProj.ob j

Ошибка 2 error LNK1169: обнаружен многократно определенный символ - один или более c:\users\...\documents\visual studio 2010\Projects\ErrProj\Debug\ErrProj.exe 1

Так что никакаяя это не трудноуловимая ошибка, а сечется компилятором влегкую.
0
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
22.11.2011, 19:10
thick_int, вы вообще читаете то, что вам пишут? Я вам помогу:
1
Цитата Сообщение от Evg Посмотреть сообщение
Так вот устроен язык Си++, что некоторые из реалиаций языка оказываются ненадёжными в этом плане
2 GOTO 1
0
Заблокирован
22.11.2011, 19:20
Ну хорошо, Вы уж извините великодушно.
Но все же ради интереса укажите тот ущербный компилятор, который такую лажу не просекает.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
22.11.2011, 20:47  [ТС]
Цитата Сообщение от thick_int Посмотреть сообщение
Но все же ради интереса укажите тот ущербный компилятор, который такую лажу не просекает
Ты вообще читаешь, что в теме пишут?
0
Заблокирован
22.11.2011, 23:54
Да Вы знаете, я так всего то с C++ знаком где-то месяц.
Конечно, еще разбираюсь слабо.
Вы уж так строго не судите новичка.

А что в теме написано, я вот так это и понял, как пишу.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
23.11.2011, 10:43  [ТС]
Пока сентенция сводится к тому, что виндузовые компиляторы ругаются на линковке, а юниксовые - нет. Потому что там и там используются разный формат исполняемого файла, и под виндой, где используется более ущербный формат, не проходят такие финты ушами, которые возможны под юниксом.

Ну и так, для общего сведения. "g++" - это имя компилятора
1
556 / 510 / 25
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
28.11.2011, 01:16
Цитата Сообщение от Evg Посмотреть сообщение
Пока сентенция сводится к тому, что виндузовые компиляторы ругаются на линковке, а юниксовые - нет. Потому что там и там используются разный формат исполняемого файла, и под виндой, где используется более ущербный формат, не проходят такие финты ушами, которые возможны под юниксом.
подробнее изложи, в чем бОльшая ущербность формата. проиллюстрируй на примере этого случая. это интересно.

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

об обобщении "виндузовые компиляторы". недавно было решено старый проект, сделанный под nt vs6 (mfc) развивать дальше ("ведь он уже есть, и успешно работает", почему не использовать оттуда куски, такой франкенштейн создать, и к нему осовремененного добавить, и будет хорошо). на то, чтобы сделать его компилируемым под vs2010, двое пахали одну неделю. потом еще столько же ушло на то, чтобы оно снова заработало. и бой продолжается. постепенно отрезаются омертвевшие части, заменяются новыми. затраты уже, по-моему, превысили затраты на новую разработку. а "всего лишь другой компилятор". и тоже виндоузовый.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
28.11.2011, 11:03  [ТС]
Цитата Сообщение от novi4ok Посмотреть сообщение
подробнее изложи, в чем бОльшая ущербность формата. проиллюстрируй на примере этого случая. это интересно
Это был всего лишь пас назад

Цитата Сообщение от thick_int Посмотреть сообщение
Но все же ради интереса укажите тот ущербный компилятор, который такую лажу не просекает
Добавлено через 4 минуты
Цитата Сообщение от novi4ok Посмотреть сообщение
а "всего лишь другой компилятор". и тоже виндоузовый
Не поверишь, но в линуксе будет то же самое. И дело не только в компиляторе, но и в библиотеках и в интерфейсах операционной системы, и в изменившихся стандартах языка. То бишь на современной операционке скомпилять большую программу 10 летней давности (особенно если на Си++ написано)

Цитата Сообщение от novi4ok Посмотреть сообщение
об обобщении "виндузовые компиляторы"
Это не обобщение, а эмпирическая сентенция на текущий момент. По результату того, где данный пример запускался. И дело не в компиляторе, а в том, как компилятор использует возможности бинарного формата, используемого в винде и в линухе
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
28.11.2011, 11:03
Помогаю со студенческими работами здесь

Объясните разницу во времени исполнения кода
Доброго времени суток. Ниже привожу 2 программы, которые отличаются лишь способом получения степени. 1 программа - через цикл for: ...

Результат исполнения функции
Результат исполнения функции D=POS('T', 'АЭРОПОРТ');

Найти результат исполнения кода
Пусть объявлена функция Number.prototype.toWord(), которая возвращает число прописью, например: (2015).toWord() // две тысячи...

Как в C++ получить результат исполнения внешней команды
Вообщем я пишу простейший код: #include &lt;stdlib.h&gt; #include &lt;iostream&gt; using namespace std; int main () { ...

В каком регистре будет находиться результат исполнения оператора add ax, bx
в каком регистре будет находиться результат исполнения оператора add ax, bx


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Жизнь в неопределённости
kumehtar 23.03.2026
Жизнь — это постоянное существование в неопределённости. Например, даже если у тебя есть список дел, невозможно дойти до точки, где всё окончательно завершено и больше ничего не осталось. В принципе,. . .
Модель здравоСохранения: работники работают быстрее после её введения.
anaschu 23.03.2026
geJalZw1fLo Корпорация до введения программа здравоохранения имела много невыполненных работниками заданий, после введения программы количество заданий выросло. Но на выплатах по больничным это. . .
1С: Контроль уникальности заводского номера
Maks 23.03.2026
Алгоритм контроля уникальности заводского (или серийного) номера на примере документа выдачи шин для спецтехники с табличной частью. Данные берутся из регистра сведений, по которому настроено. . .
Хочу заставить корпорации вкладываться в здоровье сотрудников: делаю мат модель здравосохранения
anaschu 22.03.2026
e7EYtONaj8Y Z4Tv2zpXVVo https:/ / github. com/ shumilovas/ med2. git
1С: Программный отбор элементов справочника по группе
Maks 22.03.2026
Установка программного отбора элементов справочника "Номенклатура" из модуля формы документа. В качестве фильтра для отбора справочника служит группа номенклатуры. Отбор по наименованию группы. . .
Как я обхитрил таблицу Word
Alexander-7 21.03.2026
Когда мигает курсор у внешнего края таблицы, и нам надо перейти на новую строку, а при нажатии Enter создается новый ряд таблицы с ячейками, то мы вместо нервных нажатий Энтеров мы пишем любые буквы. . .
Krabik - рыболовный бот для WoW 3.3.5a
AmbA 21.03.2026
без регистрации и смс. Это не торговля, приложение не содержит рекламы. Выполняет свою непосредственную задачу - автоматизацию рыбалки в WoW - и ничего более. Однако если админы будут против -. . .
1С: Программный отбор элементов справочника по значению перечисления
Maks 21.03.2026
Установка программного отбора элементов справочника "Сотрудники" из модуля формы документа. В качестве фильтра для отбора служит значение перечислений. / / Событие "НачалоВыбора" реквизита на форме. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru