Объект без интерфейса в C++

Вопросы по языкам программирования Си и С++.
VBTerminator
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 415
Зарегистрирован: 19.11.2008 (Ср) 20:10

Объект без интерфейса в C++

Сообщение VBTerminator » 12.01.2012 (Чт) 18:11

Всем доброго времени суток!

Как на MS Visual C++ создать контейнер, похожий на класс (с публичными и приватными функциями и переменными, конструктором и деструктором), но в то же время обладающий следующими свойствами: готовый после запуска экземпляр, невозможность создавать новые экземпляры и, что самое важное, обращение к публичным членам этого контейнера не через таблицу адресов (как в обычном классе), а напрямую (как при вызове обычной функции вне класса)?

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Объект без интерфейса в C++

Сообщение Хакер » 13.01.2012 (Пт) 9:24

Откуда сделан вывод, что методы «обычного класса» вызываются через таблицу адресов?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

VBTerminator
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 415
Зарегистрирован: 19.11.2008 (Ср) 20:10

Re: Объект без интерфейса в C++

Сообщение VBTerminator » 13.01.2012 (Пт) 19:13

Ах, да, я перепутал с таблицей виртуальных функций. А как оно на самом деле устроено?

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Объект без интерфейса в C++

Сообщение Хакер » 13.01.2012 (Пт) 19:29

Что именно перепутал?
Если название, то вопрос (мой) остаётся.
Если не название, то вопрос (твой) остаётся?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Объект без интерфейса в C++

Сообщение Хакер » 13.01.2012 (Пт) 19:32

VBTerminator писал(а): А как оно на самом деле устроено?

viewtopic.php?f=44&t=27335
Но надо учитывать, что там есть несколько ошибок, относящихся к абзацу, посвящённому VB.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

VBTerminator
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 415
Зарегистрирован: 19.11.2008 (Ср) 20:10

Re: Объект без интерфейса в C++

Сообщение VBTerminator » 13.01.2012 (Пт) 20:13

Извините, под вопросом "а как оно на самом деле устроено?" подразумевал "как класс различает обращения к одному методу различных экземпляров?"

Поясню свой самый первый вопрос. Мне нужен изолированный контейнер типа "чёрный ящик", работающий как модуль в VB, только без дублирования публичных членов этого "ящика" в глобальном пространстве имён (т. е. чтобы к его членам можно было обратиться только через "имя_контейнера.имя_члена".

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Объект без интерфейса в C++

Сообщение Хакер » 13.01.2012 (Пт) 20:14

VBTerminator писал(а):подразумевал "как класс различает обращения к одному методу различных экземпляров?"

По неявному передаваемому параметру: указателю на экземпляр.

VBTerminator писал(а):Поясню свой самый первый вопрос. Мне нужен изолированный контейнер типа "чёрный ящик", работающий как модуль в VB, только без дублирования публичных членов этого "ящика" в глобальном пространстве имён (т. е. чтобы к его членам можно было обратиться только через "имя_контейнера.имя_члена".

Где? В С++? Тогда чем не устраивает namespace?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

VBTerminator
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 415
Зарегистрирован: 19.11.2008 (Ср) 20:10

Re: Объект без интерфейса в C++

Сообщение VBTerminator » 13.01.2012 (Пт) 20:17

Хакер писал(а):Где? В С++? Тогда чем не устраивает namespeca?

Да, в C++. А namespace поддерживает приватные переменные и функции (доступные только из процедур, чьи прототипы объявлены внутри этого namespase'а)?

И да, чтобы объявить класс как статичный, необходимо писать "static class Foo", так? Спрашиваю, потому что в c++ я новичок, а компилятора под рукой пока нет.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Объект без интерфейса в C++

Сообщение Хакер » 13.01.2012 (Пт) 20:55

VBTerminator писал(а):А namespace поддерживает приватные переменные и функции (доступные только из процедур, чьи прототипы объявлены внутри этого namespase'а)?

Смотря с какой стороны смотреть. В буквальном смысле (с помощью public и private) — нет. Но ведь можно не объявлять в сторонних юнитах прототипы «приватных» функций, и проблема решена.

VBTerminator писал(а): да, чтобы объявить класс как статичный, необходимо писать "static class Foo", так?

Нет. static вообще никогда не может стоять перед class при объявлении класса.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

VBTerminator
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 415
Зарегистрирован: 19.11.2008 (Ср) 20:10

Re: Объект без интерфейса в C++

Сообщение VBTerminator » 14.01.2012 (Сб) 11:15

Хакер писал(а):Но ведь можно не объявлять в сторонних юнитах прототипы «приватных» функций, и проблема решена.

В каких "сторонних юнитах"? Что это означает?

Хакер писал(а):Нет. static вообще никогда не может стоять перед class при объявлении класса.

А, всё, осмыслил наконец фразу
http://bbs.vbstreets.ru/viewtopic.php?f=44&t=27335 писал(а):Самый простой тип методов -- статические. ... Суть здесь в том, что связывание (binding) имени вызываемого метода с конкретным адресом функции выполняется при компиляции; сам вызов ничем не отличается от вызова обычной функции ... Преимущества статических методов очевидны -- нет никаких накладных расходов на поддержание объектной структуры ...

То есть для моих целей достаточно класса со статичными методами.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Объект без интерфейса в C++

Сообщение Хакер » 14.01.2012 (Сб) 11:49

VBTerminator писал(а):В каких "сторонних юнитах"? Что это означает?

Проекты обычно состоят более чем одного файла (исходника).
Каждый файл (исходник) компилируется компилятором в объектный файл (обычно .obj в Win-мире и .o в nix-мире).
Все полученные объектные файлы затем линкером слинковываются в единый выходной файл (exe, dll, и т.п.)

К тому же объектные файлы можно собирать в своего рода архивы — библиотеки (статические библиотеки, lib-файлы в Win-мире, .a-файлы в nix-мире (a, потому что archive)).

Компилятор (как приложение, например cl.exe) вызывается для каждого исходного файла отдельно. Когда компилятор компилирует например bar.cpp, он ничего не знает о том, что раньше компилировал перед этим foo.cpp, а после будет компилировать baaz.cpp. Иными словами, при компиляции каждый файл компилируется так, как будто он единственный во вселенной, и компилятору ничего не известно о сущностях во всех остальных файлах.

Поэтому, если в одном файле размещена какая-то сущность (переменная, функция и т.п.), а ещё 40 файлов хотят к ней обращаться, то во всех этих файлах нужно объявить эту сущность, чтобы её можно было использовать. То есть, если есть функция, то в одном файле будет её код, а ещё в 30 файлах — вызов этой функции, то в этих 30 файлах должен быть прототип, чтобы компилятор (при обработке именно этих файлов) знал, что такая функция есть, что у неё такие-то аргументы такого-то типа и такой-то тип возвратов, и мог проверить соответствие типов и сообщить об ошибке. Для этой цели используют h-файлы, чтобы в каждом из 30 файлов не объявлять кучу прототипов сущностей из другого файла. Но можно объявить и вручную, без h-файлв. Поэтому люди, называющие h-файлы в общем случае библиотечными — глупцы, и киньте пожалуйста в них тухлое яйцо, если они будут при вас нести в массы эту дезинформацию (это обычно авторы книг «С/С++ для новичков» или всякие недо-преподаватели, которые сами учились по таким книжкам).

Так что, компилируя отдельный С/С++-исходник, вы можете объявить прототипы 1000 функций со случайными названиями и делать вызовы всех этих функций. То, что самих этих функций (их реализации) вообще не существует в природе — компилятору не помешает скомпилировать код в объектный файл. Просто в этом файле будет 1000 внешних зависимостей (external dependency).

      Именно поэтому глупостью являются заявления, что функции вроде printf, scanf, fopen, memcpy являются «встроенными функциями языка С» (или языка С++). Нифига они не являются. Они просто объявлены в h-файлах, то есть там объявлены их прототипы, и компилятор обрабатывает их на общих основаниях с какой-нибудь функцией «muhaha_megalol». И только потом при линковке «внешние зависимости» с одной стороны встречаются с «предлагаемыми сущнстями» с другой стороны (со стороны сишного рантайма).

      Если при линковке не указывать obj/lib-файлы (относящиеся к CRT), то линковка проекта, в исходниках которого есть обращения к таким функциям (вроде printf или strcmp), провалится даже при том, что подключены соответствующие h-файлы.

      Дело здесь в другом: существование таких функций, их набор, их функциональность, их прототипы определены стандартом языка. И стандарт предписывает не только существования компилятора, но и существование реализации всех этих функций (называмых функциями стандартной библиотеки Си, если мы говорим о Си) и возможность «слинковаться» с этими функциями.
      При этом вызов таких функций обрабатывается компилятором на общих основаниях (как вызов любой другой функции, даже несуществующей, прототип которой объявлен), линковка обрабатывается линкером тоже на общих основаниях, а само использование этих функций не является обязательным, равно как и необходимость при линковке к набору своих obj/lib-файлов добавлять obj/lib-файлы, соответствующие стандартной библиотеке (то есть содержащие реализацию этих функций).

      Но надо сделать оговорку: есть такое понятие, как intrinsic-функции. Хотя мы говорили, что сам компилятор Си плевать хотел на функции стандартной библиотеки Си, и обрабатывает их на общих основаниях, сейчас ситуация несколько отличная: для некоторых функций, соответствующих функциям стандартной библиотеки, всё-таки сделана в компилторе специфичная обработка. Такие функции называются intrinsic-ами. Например это memcpy, встретив вызов которой, компилятор не генерирует вызов «внешней функции», а генерирует машинный код, который непосредственно занимается копированием байтов.


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

Соответственно, пусть мы делаем некоторый компонент (в абстрактном смысле этого слова), который у нас у самих распределён на 10 файлов-исходников. А использоваться этот компонент будет потом из 1000 остальных файлов исходников. И мы хотим сделать некоторые функции как-бы private-ными, чтобы они были доступны только внутри исходников, относящихся к компоненту. А остальные функции — публичными, чтобы они были доступны всем остальным.

Так вот, без всяких public и private, и даже не чистом голом Си (в котором нет public и private в принципе) можно такое провернуть: просто мы делаем две версии h-файла — в одной версии объявлены прототипы и «public» и «private» методов, в другой версии — только прототипы «public» функций).

В файлах-исходниках, относящихся к самому компоненту мы подключаем один h-файлах. Файлы, не относящиеся к компоненту, подключают другой h-файл.

Таким образом, обращение к «приватной» функции из исходника-инсайдера будет успешно скомпилировано и успешно склинковано. Обращение к «приватной» функции из исходника-аутсейдера не будет успешно скомпилировано, потому что компилятор при обработке кода файла-аутсайдера до того момента, как дойти до вызова, ни разу не встретил прототип функции (он его не встретил, потому что подключалась версия h-файлов «для аутсайдеров», не содержащая прототипов «приватных» функций).

Эта система даёт возможность всё-таки вызвать private-функцию из файла-аутсайдера: достаточно просто объявить в нём прототип такой функции. Тогда компилятор уже не ругнётся, а линковка будет в любом случае успешной, потому что все сущности выставляются в «предоставляемые».

VBTerminator писал(а):То есть для моих целей достаточно класса со статичными методами.

Нет. Нужно ещё сами функции объявлять с ключевым словом static, потому что экземпляр будет всего-лишь один (и всегда один), и передача указателя на экземпляр не нужна.

И вызывать не так: object.method();, а такobject::method()
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

VBTerminator
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 415
Зарегистрирован: 19.11.2008 (Ср) 20:10

Re: Объект без интерфейса в C++

Сообщение VBTerminator » 14.01.2012 (Сб) 13:23

Большое спасибо за лекцию, теперь всё понятно. :)

Тему можно закрывать.

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Объект без интерфейса в C++

Сообщение ger_kar » 15.01.2012 (Вс) 12:03

VBTerminator писал(а):Тему можно закрывать.
А можно пока не закрывать :?:
Я кстати тоже с удовольствием прочитал лекцию, но у меня остается один вопрос.
В чем вообще разница вызовов (кроме написания) между object.method() и object::method()?
Бороться и искать, найти и перепрятать

iGrok
Артефакт VBStreets
Артефакт VBStreets
 
Сообщения: 4272
Зарегистрирован: 10.05.2007 (Чт) 16:11
Откуда: Сетевое сознание

Re: Объект без интерфейса в C++

Сообщение iGrok » 15.01.2012 (Вс) 13:03

ger_kar писал(а):В чем вообще разница вызовов (кроме написания) между object.method() и object::method()?

Во всём как бы.
Первое - это вызов метода объекта.
Второе - это вызов функции из определённого пространства имён.
label:
cli
jmp label

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Объект без интерфейса в C++

Сообщение Хакер » 15.01.2012 (Вс) 21:57

iGrok, нет. Во обоих случаях вызов метода класса. Но в первом случае метод не-static, а во втором случае — static.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

iGrok
Артефакт VBStreets
Артефакт VBStreets
 
Сообщения: 4272
Зарегистрирован: 10.05.2007 (Чт) 16:11
Откуда: Сетевое сознание

Re: Объект без интерфейса в C++

Сообщение iGrok » 15.01.2012 (Вс) 23:27

Оу. Да, действительно ошибся.
label:
cli
jmp label


Вернуться в С/С++

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4

    TopList  
cron