Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.55/55: Рейтинг темы: голосов - 55, средняя оценка - 4.55
Evg
Эксперт CАвтор FAQ
21117 / 8133 / 628
Регистрация: 30.03.2009
Сообщений: 22,448
Записей в блоге: 30
1

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

10.10.2011, 18:04. Просмотров 10443. Ответов 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;
}
Код
$ g++ t1.cc t2.cc
$ ./a.out
20
Задача из разряда "трудноуловимые ошибки"
7
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
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;...

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

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

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

21
445 / 208 / 21
Регистрация: 07.10.2011
Сообщений: 462
10.10.2011, 18:13 2
а если порядок файлов в строке
g++ t1.cc t2.cc
поменять?
0
185 / 185 / 21
Регистрация: 08.01.2011
Сообщений: 1,139
10.10.2011, 18:35 3
В Visual studio 2008 ошибка компиляции. Два раза написан метод get.
Или я не понял о чем вы?
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
10837 / 6647 / 1614
Регистрация: 25.07.2009
Сообщений: 12,427
10.10.2011, 19:21 4
Evg, и действительно, как это оно у Вас вообще скомпилировалось?
Код
$ 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
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
10.10.2011, 19:28 5
У меня тоже всё компилируется, и тоже выводит 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Эксперт С++
10837 / 6647 / 1614
Регистрация: 25.07.2009
Сообщений: 12,427
10.10.2011, 19:36 6
Цитата Сообщение от #pragma Посмотреть сообщение
Забавно
Ага... На бсде тоже скомпилировалось и тоже 20 вывело...
Код
[andrew@server2 ~/bin]$ g++ -o t t1.cc t2.cc
[andrew@server2 ~/bin]$ ./t
20
Загадка...
0
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
10.10.2011, 19:51 7
Странно, когда перенёс x в public, один раз таки выдало 10...
Такое ощущение, что при вызове c.get() вызывается конструктор объекта класса из t2.cc
0
Evg
Эксперт CАвтор FAQ
21117 / 8133 / 628
Регистрация: 30.03.2009
Сообщений: 22,448
Записей в блоге: 30
10.10.2011, 20:27  [ТС] 8
Лучший ответ Сообщение было отмечено как решение

Решение

Цитата Сообщение от 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
235 / 208 / 29
Регистрация: 08.06.2011
Сообщений: 467
10.10.2011, 20:39 9
Цитата Сообщение от #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
21117 / 8133 / 628
Регистрация: 30.03.2009
Сообщений: 22,448
Записей в блоге: 30
11.10.2011, 10:43  [ТС] 10
Лучший ответ Сообщение было отмечено как решение

Решение

объяснение
Всё растёт из того, что стандарт Си++ требует того, чтобы 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 11
Что-то уж очень противоречивое.
А как все это согласуется с тем, что любой объект в программе может быть определен только один раз.
Здесь явно это правило нарушено.
0
Evg
Эксперт CАвтор FAQ
21117 / 8133 / 628
Регистрация: 30.03.2009
Сообщений: 22,448
Записей в блоге: 30
22.11.2011, 13:38  [ТС] 12
Цитата Сообщение от thick_int Посмотреть сообщение
Что-то уж очень противоречивое.
А как все это согласуется с тем, что любой объект в программе может быть определен только один раз.
Здесь явно это правило нарушено.
Объект определён ровно один раз. А два раза определён метод. Если ты два раза напишешь функцию на Си, то у тебя поломается на линковке. А здесь исходник содержит ошибку, но на линковке ошибка не проявилась. Так вот устроен язык Си++, что некоторые из реалиаций языка оказываются ненадёжными в этом плане. Потому что придумать язык мало, надо ещё и понимать, как будет работать компилятор с него и какие при этом могут оказаться подводные камни
0
Заблокирован
22.11.2011, 18:22 13
Ну уж не знаю, каким Вы компилятором пользуетесь, но я все таки не поленился перекопировал код Вашей так называемой ошибки и вот, что выдает 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.obj

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

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

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

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

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

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

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

Цитата Сообщение от novi4ok Посмотреть сообщение
об обобщении "виндузовые компиляторы"
Это не обобщение, а эмпирическая сентенция на текущий момент. По результату того, где данный пример запускался. И дело не в компиляторе, а в том, как компилятор использует возможности бинарного формата, используемого в винде и в линухе
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
28.11.2011, 11:03

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

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

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

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

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

Ошибки во время исполнения программы
Приветствую всех форумчян. Во время исполнения программы система выдает 2 ошибки (см. вложения)....

Разное время исполнения программы
&quot;Баловался&quot; с кодом питона и наткнулся на интересный результат: один и тот же код выполняется...


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

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

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