0 / 0 / 0
Регистрация: 20.12.2016
Сообщений: 98
1

Глобальное разрешение ::

15.04.2017, 19:55. Показов 2736. Ответов 27
Метки c++ (Все метки)

Author24 — интернет-сервис помощи студентам
Для чего нужно объявить прототип метода в классе, а описывать его уже за пределами класса?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
15.04.2017, 19:55
Ответы с готовыми решениями:

очень глобальное определение
скачал curl - там функции не добавлены в импорт, следственно в скомпилированной либе их нет. вот в...

вопрос про глобальное пространство имен
#include <iostream> namespace { int a = 1; } int main() { using std::cout; int a = 5;

Глобальное считывание комбинаций win api
Всем привет, есть такая штука как autoHotKey смысл ее действия это считывать нажатия клавиш или...

Глобальное задание, охватывающее почти весь с++
Здравствуйте, недавно тут начал с++ изучать, дошел до ООП. Но это только теория, вся практика...

27
7774 / 6544 / 2981
Регистрация: 14.04.2014
Сообщений: 28,565
15.04.2017, 20:23 2
Чтобы разделить на h и cpp. Или просто для удобства, если разделения нет.
0
0 / 0 / 0
Регистрация: 20.12.2016
Сообщений: 98
15.04.2017, 21:19  [ТС] 3
Не, я про другое, вот:

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
77
78
79
80
81
82
83
84
85
86
87
class fraction
    {
    private:
        int numerator;
        int denominator;
    public:
        fraction () : numerator (0), denominator (0)
        {}
        
        fraction (int n, int d) : numerator (n), denominator (d)
        {}
        
        char sim = '/';
        
        void input ()
        {
            cout << "Введите дробь - ";
            cin >> numerator >> sim >> denominator;
        }
        
        void add (Fraction f1, Fraction f2)
        {
            numerator = f1.numerator * f2.denominator + f1.denominator * f2.numerator;
            denominator = f1.denominator * f2.denominator;
        }
        void sub (Fraction f1, Fraction f2)
        {
            numerator = f1.numerator * f2.denominator - f1.denominator * f2.numerator;
            denominator = f1.denominator * f2.denominator; 
        }
        void mul (Fraction f1, Fraction f2)
        {
            numerator = f1.numerator * f2.denominator;
            denominator = f1.denominator * f2.denominator;
        }
        void div (Fraction f1, Fraction f2)
        {
            numerator = f1.numerator * f2.denominator;
            denominator = f1.denominator * f2.numerator;
        }
        
        void display () const
        {
            cout << cout << numerator << "/" << denominator;    
        }
        void lowterms ();
    };
    ////////////////////////////////////////////////////////////////////////////////////////////
    void fraction :: lowterms ()
    
    {
        long tnum, tden, temp, gcd;
        
        tnum = labs(numerator);              // используем неотрицательные
        
        tden = labs(denominator);            // значения (нужен cmath)
   
        if( tden == 0 )                      // проверка знаменателя на 0
        { 
        cout << "Недопустимый знаменатель!"; 
        exit(1); 
        }
        
        else if( tnum == 0 )                 // проверка числителя на 0
        { 
        numerator = 0; 
        denominator = 1;                     // нахождение наибольшего общего делителя
        return;     
        }
        
   while(tnum !=0)
   {
     if( tnum < tden )                       // если числитель больше знаменателя,
     { 
        temp=tnum; 
        tnum=tden;                           //меняем их местами
        tden=temp; 
     } 
     
     tnum = tnum - tden;                     // вычитание
    }
   
   gcd = tden;                               // делим числитель и знаменатель на
   numerator = numerator / gcd;              // полученный наибольший общий делитель
   denominator = denominator / gcd;
  }
int main()
Для чего здесь вынесен метод за класс. Или так же еще выносят поле класса и присваивают какое-нибудь значение и т.д.
0
"C with Classes"
1642 / 1399 / 523
Регистрация: 16.08.2014
Сообщений: 5,869
Записей в блоге: 1
15.04.2017, 21:23 4
Tanya228, что бы метод не был inline то есть что бы метод был не встраиваемый а вызываемый.

Добавлено через 1 минуту
Цитата Сообщение от Tanya228 Посмотреть сообщение
Или так же еще выносят поле класса и присваивают какое-нибудь значение
статические поля класса
0
0 / 0 / 0
Регистрация: 20.12.2016
Сообщений: 98
15.04.2017, 21:28  [ТС] 5
Т.е. для того, чтобы использовать один класс в разных программах, а при надобности просто добавлять к нему другие методы как раз этой операцией?
0
"C with Classes"
1642 / 1399 / 523
Регистрация: 16.08.2014
Сообщений: 5,869
Записей в блоге: 1
15.04.2017, 21:30 6
Tanya228, нет, почитай про inline методы и static поля класса.
0
1272 / 1029 / 470
Регистрация: 25.12.2016
Сообщений: 3,333
15.04.2017, 21:37 7
Цитата Сообщение от Tanya228 Посмотреть сообщение
Для чего здесь вынесен метод за класс.
По большей части для удобства, чтобы не загромождать описание класса.
1
863 / 451 / 89
Регистрация: 10.06.2014
Сообщений: 2,643
15.04.2017, 21:43 8
_stanislav,
А с чего вы взяли, что при определении метода указанным образом, компиляторы не применят inline?
1
"C with Classes"
1642 / 1399 / 523
Регистрация: 16.08.2014
Сообщений: 5,869
Записей в блоге: 1
15.04.2017, 21:57 9

Не по теме:

Undisputed, поспорить хочешь? 8-)



Добавлено через 4 минуты
Имейте в виду, что директива inline – это совет, а не команда компилятору. Совет может быть сформулирован явно или неявно. Неявный способ заключается в определении встроенной функции внутри определения класса.
©Скотт Мэйерс
0
0 / 0 / 0
Регистрация: 20.12.2016
Сообщений: 98
15.04.2017, 22:02  [ТС] 10
Undisputed, а для чего тогда указывать таким образом? просто, чтоб в классе не нагромождать?
0
Комп_Оратор)
Эксперт по математике/физике
8945 / 4699 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
15.04.2017, 23:18 11
Tanya228, у разделения объявления и определения есть более веские причины. Когда потребуется перекрёстное включение классов Вы увидите, что иначе не обойтись. Дело в том, что иногда комбинация опережающего объявления и использование указателя недостаточно, так как нужно вызывать методы. Однако включить хедеры связываемых классов друг в друга нельзя не получив двойных объявлений. Тогда в одном классе включают хедер в cpp файл другого класса из пары которая связывается. Это трудно объяснять и громоздко иллюстрировать. Однако, когда Вам это потребуется, Вы сможете спросить более конкретно. Пока что, достаточно понять, что это способ разделения интерфейса и реализации. То есть, дорога к свету.
0
7 / 7 / 2
Регистрация: 28.04.2015
Сообщений: 21
15.04.2017, 23:24 12
Цитата Сообщение от _stanislav Посмотреть сообщение
что бы метод не был inline то есть что бы метод был не встраиваемый а вызываемый.
Бред, такое объявление делается только для удобства. GCC или VC++ с флагом -O2 спокойно инлайнят любые методы, если считают что так будет производительнее.
За исключением функций которым жестко запрещено встраивание (__declspec(noinline), #pragma function(...), etc...)
0
284 / 232 / 114
Регистрация: 07.09.2016
Сообщений: 584
16.04.2017, 01:33 13
какое нахрен удобство. если кому-то удобно - то это побочный эффект.
уже написали, что это для разделения реализации и интерфейса.
если это слишком звучит слишком абстрактно, то вот еще один конкрентый пример:
есть собранная библиотека в либ файле. кто, как и из каких исходников ее собрал - это не сильно важно для того, чтобы ее использовать. для использования нужен интерфейс (все, что в инклудниках), и собранная библиотека в lib файле. либ файл может быть собран из секретных исходников, до которых у вас доступа нет, он может быть собран из исходников на другом языке программирования, он может просто долго собираться, если его с нуля билдить. если библиотек в проекте много, то банальная пересборка проекта может длиться часами и т.д. и т.п.
1
с++
1282 / 523 / 225
Регистрация: 15.07.2015
Сообщений: 2,562
16.04.2017, 09:35 14
Ну скорее всего это сделанно для того что бы вам показать что в классе не стоит реализовывать методы так как это усложняет читаймость, хотя при этом это можно делать и будет работать так и так, еще же можно реализацию метода положить и в другой файл.
1
Комп_Оратор)
Эксперт по математике/физике
8945 / 4699 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
16.04.2017, 10:01 15
Tanya228, вот недавно была похожая тема:
Нюансы объявления класса
посмотрите. Правила (ODR) не позволяют определять переменную дважды в одной области видимости и это может вызвать трудности, когда определение двух зависимых классов нуждается в ссылках друг на друга. Я уже говорил, что это несколько громоздко и для иллюстрации и для понимания. При решении реальной задачи, где без этого не обойтись, Вам придётся это разобрать. Иначе, возможно, Вы сочтёте это сложным. Поэтому и говорю, - считайте пока, что это имеет смысл и оставьте до поры.
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
16.04.2017, 12:54 16
Цитата Сообщение от _stanislav Посмотреть сообщение
Tanya228, что бы метод не был inline то есть что бы метод был не встраиваемый а вызываемый.
Цитата Сообщение от Undisputed Посмотреть сообщение
А с чего вы взяли, что при определении метода указанным образом, компиляторы не применят inline?
господин _stanislav прав.
но не совсем раскрыл момент.

действительно, определенные прямо в теле класса методы являются inline
в отличие от тех, что были определены в cpp.

главное различие между inline функциями и не inline,
заключается в том,
что inline обладают внутренним связыванием.
в то время, как обычные функции - внешним.

и вот в чем разница между этими двумя видами связывания?
представьте себе, что вы разрабатываете библиотеку foo.lib.
она собирается отдельно.
а потом уже пользовательское приложение с нею линкуется:

C++
1
2
3
//foo.h
 
void foo(); //<--- внешнее связывание
C++
1
2
3
4
5
6
7
//foo.cpp
#include <iostream>
 
void foo() //<--- внешнее связывание
{
    std::cout << "hello, world\n";
}
компиляторы нынче достаточно умны.
однако дело не в теоретической возможности,
встроить функцию с external linkage.
а в практической целесообразности.

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

а то, что торчит прямо в хедерах,
вполне себе безопасно можно встраивать.
1
863 / 451 / 89
Регистрация: 10.06.2014
Сообщений: 2,643
16.04.2017, 15:45 17
Цитата Сообщение от hoggy Посмотреть сообщение
представьте себе, что компилятор
таки встроил функцию библиотеки.
ну и как потом пользователи смогут её вызывать?
ИМХО компилятор же видит когда цепляется уже скомпилированная либа, соответственно может сообразить как организовать код в отношении кода из подключаемой библиотеки, и так же видит код который нужно скомпилировать и заинлайнить...

так же не понятно почему компилятор при генерации машинного кода с учетом скомпилированной библиотеки не может прикинуться что на самом деле никакой либы нет? компилятор же знает какой код должен быть выполнен с учетом подключенной библиотеки... или нет? в таком случае использование даже высокопроизводительных библиотек становится не таким уж и высокопроизводительным удовольствием ибо в результате исполняемый код будет оставлять желать лучшего....
0
Неэпический
17869 / 10634 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
16.04.2017, 16:26 18
Цитата Сообщение от hoggy Посмотреть сообщение
что inline обладают внутренним связыванием.
Эт где Вы прочитали?
Можно ссыль в стандарт?
inline же никак не влияет на связывание.
1
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
16.04.2017, 22:05 19
Цитата Сообщение от Croessmah Посмотреть сообщение
Эт где Вы прочитали?
Можно ссыль в стандарт?
inline же никак не влияет на связывание.
ну например, в стандарте есть упоминание,
что встраиваемые функции имеют иммунитет
против ошибки множественного определения.

но только функции с внутренним
связыванием имеют такой иммунитет.


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//foo.h
#pragma once
 
// поскольку все функции
// определенные в хедере имеют внутреннее связывания
// то данный хедер можно включать в разные ед. трансляций
// не опасаясь ошибок множественного определения
 
static void foo(){}
 
namespace {
    
    void bar(){}
 
}//namespace 
 
 
inline void baz(){}
Добавлено через 12 минут
Цитата Сообщение от Undisputed Посмотреть сообщение
ИМХО компилятор же видит когда цепляется уже скомпилированная либа
1.
создаете статическую библиотеку.
принудительно заставляете компилятор сделать
функцию с external linkage inline
получаете уже готовый скомпилированный код

2.
создаете проект.exe
линкуетесь с библиотекой созданной ранее.

3.
пытаетесь вызвать функцию,
которая по факту была встроена.

4.
получаете ошибку линковки:
а функция то тю-тю.
0
Неэпический
17869 / 10634 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
16.04.2017, 22:55 20
Цитата Сообщение от hoggy Посмотреть сообщение
но только функции с внутренним
связыванием имеют такой иммунитет.
Сделайте статическую переменную в функции и посмотрите.
Если бы связывание было внутренним - это были бы
разные переменные в каждой единице трансляции.
Цитата Сообщение от hoggy Посмотреть сообщение
что встраиваемые функции имеют иммунитет
против ошибки множественного определения.
Согласно стандарту остается лишь одна реализация,
остальные при сборке просто выпиливаются.
Какая остается? Зависит от левой пятки компилятора.
Собственно, поэтому функция должна иметь одинаковое
определение во всех единицах трансляции где используется,
иначе потом компилятор оставит только одну и будет сюрприз,
хотя всё и соберется без проблем.
0
16.04.2017, 22:55
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
16.04.2017, 22:55
Помогаю со студенческими работами здесь

Как сделать глобальное пространство имени?
Вот так не работает: global.h extern namespace matrix { mat4 proj; mat4 view; ...

Глобальное задание массива в качестве параметра функции
Дамы и господа, такой вопрос. Работаю с классами и функциями, и мне необходимо сделать так, чтобы...

Глобальное переопределение "operator <<" для char *
Здравствуйте. Привожу пример для демонстрации проблемы. Помогите пожалуйста в ее устранении или...

Разрешение приложения - чтобы приложение подстраивалось под разрешение экрана
Можно ли средствами c++ bulder сделать так, чтобы разрешение приложения подстраивалось под...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru