Линковка - как понять C#-овскими мозгами (на примере)?
От: Shmj Ниоткуда  
Дата: 05.01.23 10:48
Оценка: -2 :)
Вот пример, чтобы не быть голословным: https://github.com/linuxdeepin/dde-file-manager/blob/master/src/dde-file-manager/singleapplication.h

#include <QtGlobal>

#include <DApplication>
#include <durl.h>

QT_BEGIN_NAMESPACE
class QLocalServer;
class QLocalSocket;
QT_END_NAMESPACE


Здесь есть include а есть просто декларация class QLocalServer. А ведь можно сделать и #include <QLocalServer> и тоже будет работать.

В чем разница и как лучше — включать или просто объявлять?

Для классов не применимо extern а для функций, к примеру, применимо. Эта запись class QLocalServer; — эквивалент extern-а для функций?
Re: Линковка - как понять C#-овскими мозгами (на примере)?
От: sergii.p  
Дата: 05.01.23 11:21
Оценка: 6 (1) +1
Здравствуйте, Shmj, Вы писали:

S>В чем разница и как лучше — включать или просто объявлять?



Но не всё однозначно конечно. При объявлении несколько сложнее рефакторинг (заменили class на struct, поменяли имя и т. д.). Да и вообще это выглядит как костыль (а на самом деле таким и является).
Re: Линковка - как понять C#-овскими мозгами (на примере)?
От: rg45 СССР  
Дата: 05.01.23 12:01
Оценка: 6 (1)
Здравствуйте, Shmj, Вы писали:

S>Вот пример, чтобы не быть голословным: https://github.com/linuxdeepin/dde-file-manager/blob/master/src/dde-file-manager/singleapplication.h


S>
S>#include <QtGlobal>

S>#include <DApplication>
S>#include <durl.h>

S>QT_BEGIN_NAMESPACE
S>class QLocalServer;
S>class QLocalSocket;
S>QT_END_NAMESPACE
S>


S>Здесь есть include а есть просто декларация class QLocalServer. А ведь можно сделать и #include <QLocalServer> и тоже будет работать.

S>В чем разница и как лучше — включать или просто объявлять?

Можно не значит нужно. Общий принцип такой, что не следует подключать заголовок с полным определением класса там, где можно обойтись предварительным объявлением. Минимизация включения заголовочных файлов нужна не только для уменьшения времени компиляции, но и для уменьшения связности кода и предотвращения зацикленности включений. Подробнее можно почитать здесь: http://programming-lang.com/ru/comp_programming/satter/0/j39.html.

S>Для классов не применимо extern а для функций, к примеру, применимо. Эта запись class QLocalServer; — эквивалент extern-а для функций?


Тут нужно бы начать с того, что немного разобраться с понятиями: есть объявления (declarations), а есть определения (definitions). Очень часто объявление одновременно является и определением. extern же — это разновидность спецификации связывания (linkage). External linkage означает, что имя доступно в разных единицах трансляции и обрабатывается линковщиком. Фунцкции, классы и неконстантные объекты, объявленные в области видимости пространств имен, по умолчанию имеют внешнее связывание (external linkage), поэтому от явной спецификации extern мало пользы и ее чаще всего опускают.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 05.01.2023 12:22 rg45 . Предыдущая версия . Еще …
Отредактировано 05.01.2023 12:20 rg45 . Предыдущая версия .
Отредактировано 05.01.2023 12:16 rg45 . Предыдущая версия .
Re[2]: Линковка - как понять C#-овскими мозгами (на примере)?
От: rg45 СССР  
Дата: 05.01.23 12:41
Оценка: +1
Здравствуйте, sergii.p, Вы писали:

SP>Но не всё однозначно конечно. При объявлении несколько сложнее рефакторинг (заменили class на struct, поменяли имя и т. д.). Да и вообще это выглядит как костыль (а на самом деле таким и является).


Можно создавать особенные заголовочные файлы, которые состоят только из предварительных объявлений. Включение таких файлов вполне безобидно, но в некоторых случаях может избавить от общирных изменений по коду после рефакторингов.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re: Линковка - как понять C#-овскими мозгами (на примере)?
От: LaptevVV Россия  
Дата: 06.01.23 03:07
Оценка: +1
S>
S>#include <QtGlobal>

S>#include <DApplication>
S>#include <durl.h>

S>QT_BEGIN_NAMESPACE
S>class QLocalServer;
S>class QLocalSocket;
S>QT_END_NAMESPACE
S>


Это не линковка.
Линковка — это когда работает линкер.
Здесь до линкера еще ехать и ехать.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: Линковка - как понять C#-овскими мозгами (на примере)?
От: vsb Казахстан  
Дата: 08.01.23 05:05
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Вот пример, чтобы не быть голословным: https://github.com/linuxdeepin/dde-file-manager/blob/master/src/dde-file-manager/singleapplication.h


S>
S>#include <QtGlobal>

S>#include <DApplication>
S>#include <durl.h>

S>QT_BEGIN_NAMESPACE
S>class QLocalServer;
S>class QLocalSocket;
S>QT_END_NAMESPACE
S>


S>Здесь есть include а есть просто декларация class QLocalServer. А ведь можно сделать и #include <QLocalServer> и тоже будет работать.


S>В чем разница и как лучше — включать или просто объявлять?


Разница в том, что файл QLocalServer здоровый и парсить его долго и сложно. При этом для объявления указателя на этот класс тебе этот файл не нужен. Тебе нужно только сообщить компилятору о самом факте существования такого класса. Поэтому в целом оба варианта будут работать, но вариант без include будет компилироваться быстрей. При этом, конечно, в файле с реализацией, где ты будешь вызывать методы этого класса, тебе уже нужен нормальный include.

По сути это костыль для кривого C++ в котором нет модулей. В нормальных языках такой нужды нет.

Ещё такой подход может использоваться в рекурсивных структурах. Когда тебе надо объявить указатель на структуру, которая объявляется поздней.

S>Для классов не применимо extern а для функций, к примеру, применимо. Эта запись class QLocalServer; — эквивалент extern-а для функций?


extern используется для глобальных переменных. Для функций extern использовать смысла не имеет, они всегда extern. Просто напиши определение функции без тела. Я не думаю, что есть смысл проводить аналогию тут, мне кажется это разные вещи.
Re[2]: Линковка - как понять C#-овскими мозгами (на примере)?
От: pagid_ Россия  
Дата: 08.01.23 11:35
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>Линковка — это когда работает линкер.

Валерий Викторович, компановщик или редактор связей
В присутствии студентов тоже "литнкер"?
Re[3]: Линковка - как понять C#-овскими мозгами (на примере)?
От: LaptevVV Россия  
Дата: 08.01.23 11:37
Оценка: +1
LVV>>Линковка — это когда работает линкер.
_>Валерий Викторович, компановщик или редактор связей
_>В присутствии студентов тоже "литнкер"?
Я им про все три термина рассказываю.
И схему алгоритма компоновки (статической) тоже рассказываю
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: Линковка - как понять C#-овскими мозгами (на примере)?
От: Skorodum Россия  
Дата: 13.01.23 15:18
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>Но не всё однозначно конечно. При объявлении несколько сложнее рефакторинг (заменили structна struct, поменяли имя и т. д.).

В чем проблема с заменой class/struct?
Переименование и forward declaration для IDE сейчас не проблема.

SP>Да и вообще это выглядит как костыль (а на самом деле таким и является).

Это логичное решение при разделении на cpp/h.
Re: Линковка - как понять C#-овскими мозгами (на примере)?
От: Pzz Россия https://github.com/alexpevzner
Дата: 19.01.23 22:33
Оценка:
Здравствуйте, Shmj, Вы писали:

S>
S>QT_BEGIN_NAMESPACE
S>class QLocalServer;
S>class QLocalSocket;
S>QT_END_NAMESPACE
S>


Не надо так делать. Это они от какого-то большого отчаянья.

S>Здесь есть include а есть просто декларация class QLocalServer. А ведь можно сделать и #include <QLocalServer> и тоже будет работать.


#include принесет с собой декларацию класса, его методов и всё такое.

Просто объявление класса сообщит компилятору, "слушай, компилятор, вот есть такой класс XXX. ты там особо не ругайся, если он будет упомянут в коде". Это называется, forward declaration.

Такое иногда бывает надо, если в пределах .h-ника не получается так расположить декларации, чтобы не было ссылок вперед. Например, из-за циклической зависимости между декларациями. Но делающий так должен контролировать и forward declaration, и настоящее объявление.

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

S>В чем разница и как лучше — включать или просто объявлять?


Включать.

S>Для классов не применимо extern а для функций, к примеру, применимо. Эта запись class QLocalServer; — эквивалент extern-а для функций?


extern нужен только для переменных. Для функций он ничего нового компилятору не сообщает.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.