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

Методы вызываются через указатель на объект класса; Как компилятор определяет, какой из методов надо вызвать? - C++

Войти
Регистрация
Восстановить пароль
Другие темы раздела
C++ кодировка русского шрифта http://www.cyberforum.ru/cpp-beginners/thread804419.html
/*вроде в консоли выходят русский шрифт, но когда выводится новый массив то выходят какие каракули) посмотрите пожалуйста кто умеет*/ #include <iostream> using namespace std; struct WORKER { char surname; // фамилия char initials; // инициалы char post; // должность int date; // год рождения
C++ Класс таблиц баз данных и класс записей в таблице(реляционная таблица). Предусмотреть класс связей между таблицами Здравствуйте! Никак не могу продумать структуру этой программы. Проходим наследование, но я все равно не знаю, как его здесь применить. Как нужно построить эти классы, чтобы получилась грамотная иерархия? Как вообще должен выглядеть класс связей между таблицами? Я долго билась над этим, но пока получился только трехмерный динамический массив. Вот код, я его забросила, очевидно, что это бред... http://www.cyberforum.ru/cpp-beginners/thread804360.html
Компилятор Borland C++
Создал программу, которая записывает определённые значения в файл. ofstream fout("out.txt", ios::out); То есть эта запись означает, что файл должен создаться(и записываться), в той папке, в которой лежит соответствующий исполняемый модуль. Сначала у меня и исполняемые модули не появлялись в папке, они находились в папке BIN , через опции я явно указал директорию, в которой должны...
C++ Обращение к элементам массива структур
Вводим n-ое количество имен и количество оценок каждому из имен.(студент - оценки) #include <iostream> using namespace std; int main() { int i,j,k,n=2; int sr;
C++ Косинус 90 градусов равняется бреду http://www.cyberforum.ru/cpp-beginners/thread804345.html
// var_7.cpp: определяет точку входа для консольного приложения. // #include "stdafx.h" #include <math.h> #define _USE_MATH_DEFINES #include <iostream> #include <conio.h> #include <iomanip>
C++ Перевод дробной части из десятичной в восьмеричною Отобразить этапи перевода дробной части из десятичной в восьмиричную. подробнее

Показать сообщение отдельно
kravam
быдлокодер
1696 / 875 / 44
Регистрация: 04.06.2008
Сообщений: 5,342

Методы вызываются через указатель на объект класса; Как компилятор определяет, какой из методов надо вызвать? - C++

10.03.2013, 08:39. Просмотров 675. Ответов 12
Метки (Все метки)

Ребята, если вникать, то вообще ничё непонятно. Вот смотрите: пусть у нас есть абстрактный класс abstr (abstr.h) и в нём определено, например 10 функций виртуальных функции. Эти функции реализованы в каком-то статическом классе stats (файлы stats.h и stats.cpp). И пусть мы вызываем например две из них в main.cpp, вот так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//main.cpp
#include <windows.h>
#include <stdio.h>
#include "abstr.h"
#include "stats.h"
 
 
int main() {
 SetConsoleCP(1251);
 SetConsoleOutputCP(1251);
 
 abstr* p= new stats; 
 
 p->foo_0();  
 p->foo_1();  
 delete p; 
 
 getchar ();
 return 0;
}
Теперь мы всё это дело компилим, то есть main.cpp отдельно, stats.cpp отдельно. И получаем 2 файла main.o и stats.o. Можно и нужно посмотреть их содержание утилитой nm:

Bash
1
2
nm main.o 
nm stats.o
Так, а теперь кропаем экзешник:

Bash
1
g++ -o main.exe main.o stats.o
И запускаем. Пока всё предсказуемо. А теперь внимание, фокус-покус. Измените main.cpp вот так (например):

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//main.cpp
#include <windows.h>
#include <stdio.h>
#include "abstr.h"
#include "stats.h"
 
int main() {
 SetConsoleCP(1251);
 SetConsoleOutputCP(1251);
 
 abstr* p= new stats; 
 
 p->foo_4();  
 p->foo_5();  
 delete p; 
 
 getchar ();
 return 0;
}
И снова скомпильте- вы получите *.o файлы, АБСОЛЮТНО ИДЕНТИЧНЫЕ тем, что были раньше (смотрим утилитой nm). Но экзешник у вас получится совершенно другой- а именно с функциями foo_4 и foo_5 вместо foo_0 и foo_1

Два абсолютно одинаковых набора сырцов (хотя сырцами называют исходники, но я щас говорю про *.o файлы) и два абсолютно разных экзешника!

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Вы мне можете возразить- функции, которые вызовутся, определяются непосредственно во время исполнения. А вот ни фига подобного. Во время исполнения может быть определён тип статического классса, к которому будет неявно приведён указатель p- (тут, собсно, ничё нового. Но у меня для простоты один тип- stats). А вот функции, которые вызовутся, становятся известны только на этапе линковки и не позже! Хотя бы даже из того это следует, что: мы линкуем, допустим, второй пример и у нас в экзешнике оказываются ИМЕНО две нужных функции из 10-ти, foo_4 и foo_5, остальных и в помине там нет.

Так как компилятор из двух совершенно одинаковых наборов символов определяет- что в этот раз надо вставить в тело экзешника код функции такой-то, а в другой раз код функции такой-то. Где он в файле main.o видит имена этих функций?

И ещё раз повторю: аргумент "функции, которые необходимо вызвать, находятся через указатель p" (я, кстати, смотрел это дело в отладчике OllyDbg), неправилен. Ибо через этот указатель они могут найтись только лишь во время исполнения программы. А как мы выяснили, они к этому времени уже находятся в экзешнике. Причём только нужные функции, и никаких лишних.

В общем, ступор тот ещё.

Спасибо, кто откликнется. Файлы прилагаю.

это исходники будут
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//main.cpp
#include <windows.h>
#include <stdio.h>
#include "abstr.h"
#include "stats.h"
 
 
int main() {
 SetConsoleCP(1251);
 SetConsoleOutputCP(1251);
 
 abstr* p= new stats; 
 
 p->foo_0();  
 p->foo_1();  
 delete p; 
 
 getchar ();
 return 0;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++=
 
//abstr.h
#ifndef _ABSTR_H
#define _ABSTR_H
class abstr {
 public:
  virtual void foo_0  ()= 0;
  virtual void foo_1  ()= 0;
  virtual void foo_2  ()= 0;
  virtual void foo_3  ()= 0;
  virtual void foo_4  ()= 0;
  virtual void foo_5  ()= 0;
  virtual void foo_6  ()= 0;
  virtual void foo_7  ()= 0;
  virtual void foo_8  ()= 0;
  virtual void foo_9  ()= 0;
};
#endif
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
//stats.h
#ifndef _STATS_H
#define _STATS_H
#include "abstr.h"
class stats: public abstr {
 public:
  void foo_0  ();
  void foo_1  ();
  void foo_2  ();
  void foo_3  ();
  void foo_4  ();
  void foo_5  ();
  void foo_6  ();
  void foo_7  ();
  void foo_8  ();
  void foo_9  ();
};
#endif
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
//stats.cpp
#include "stats.h"
#include <stdio.h>
 
void stats::foo_0 ()  {printf ("ноль__\n");};
void stats::foo_1 ()  {printf ("один__\n");};
void stats::foo_2 ()  {printf ("два___\n");};
void stats::foo_3 ()  {printf ("три___\n");};
void stats::foo_4 ()  {printf ("четыре\n");};
void stats::foo_5 ()  {printf ("пять__\n");};
void stats::foo_6 ()  {printf ("шесть_\n");};
void stats::foo_7 ()  {printf ("семь__\n");};
void stats::foo_8 ()  {printf ("восемь\n");};
void stats::foo_9 ()  {printf ("девять\n");};
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++

компилить:
Bash
1
2
3
4
5
6
7
8
9
10
11
rem кропаем stats.o
del stats.o
g++ -c stats.cpp
 
rem кропаем main.o
del main.o
g++ -c main.cpp
 
rem кропаем main.exe
del main.exe
g++ -o main.exe main.o stats.o
А тут на всякий случай АБСОЛЮТНО одинаковые файлы main.o в первом и во втором случаях

//m_01.txt
00000000 b .bss
00000000 d .data
00000000 r .eh_frame
00000000 r .eh_frame$_ZN5abstrC2Ev
00000000 r .eh_frame$_ZN5statsC1Ev
00000000 r .eh_frame$getchar
00000000 r .rdata$_ZTI5abstr
00000000 r .rdata$_ZTS5abstr
00000000 r .rdata$_ZTV5abstr
00000000 t .text
00000000 t .text$_ZN5abstrC2Ev
00000000 t .text$_ZN5statsC1Ev
00000000 t .text$getchar
U _SetConsoleCP@4
U _SetConsoleOutputCP@4
00000000 T __ZN5abstrC2Ev
00000000 T __ZN5statsC1Ev
00000000 R __ZTI5abstr
00000000 R __ZTS5abstr
00000000 R __ZTV5abstr
U __ZTV5stats
U __ZTVN10__cxxabiv117__class_type_infoE
U __ZdlPv
U __Znwj
U ___cxa_pure_virtual
U ___main
U __filbuf
U __imp___iob
00000000 T _getchar
00000000 T _main

+++++++++++++++++++++++++++++++++++++++=

//m_45.txt
00000000 b .bss
00000000 d .data
00000000 r .eh_frame
00000000 r .eh_frame$_ZN5abstrC2Ev
00000000 r .eh_frame$_ZN5statsC1Ev
00000000 r .eh_frame$getchar
00000000 r .rdata$_ZTI5abstr
00000000 r .rdata$_ZTS5abstr
00000000 r .rdata$_ZTV5abstr
00000000 t .text
00000000 t .text$_ZN5abstrC2Ev
00000000 t .text$_ZN5statsC1Ev
00000000 t .text$getchar
U _SetConsoleCP@4
U _SetConsoleOutputCP@4
00000000 T __ZN5abstrC2Ev
00000000 T __ZN5statsC1Ev
00000000 R __ZTI5abstr
00000000 R __ZTS5abstr
00000000 R __ZTV5abstr
U __ZTV5stats
U __ZTVN10__cxxabiv117__class_type_infoE
U __ZdlPv
U __Znwj
U ___cxa_pure_virtual
U ___main
U __filbuf
U __imp___iob
00000000 T _getchar
00000000 T _main

Реезультаты сравнения stats.o самого с собой не выкладываю- и так понятно, он же не менялся от компиляции к компиляции, потому что не менялся stats.cpp
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
 
Текущее время: 07:05. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru