2013-08-05 2 views
3

Я действительно хочу использовать D, потому что его языковые конструкции делают так много вещей, которые я заботиться о лучше, чем C++, но почти заставили GC (issue handled [sort of] here), чуть менее мощный оператор перегрузки (кроме opDispatch. opDispatch является сексуальным), и следующий вопрос меня отвлекает.расщепление объявление из определения

Возможно ли в D разбить объявление метода из определения? Если да, то как? Если нет, то почему?

Мотивационный пример для «как»: предоставить небольшой заголовочный файл функций интерфейса рядом с двоичным объектом, например, с заголовком и библиотекой C, чтобы скрыть реализацию от глаз писателя пользователя код. Предпочтение: не зависит от того, был ли пользовательский код взломан сборщик мусора или просто компилируется без времени выполнения (such as this найдено в комментариях here).

+0

Подробнее о файлах интерфейса D. – DejanLekic

+0

@DejanLekic Я вижу только файлы интерфейса D, указанные в разделах документации в компиляторах. Является ли это компилятором или компилятором или языком? EDIT: Blargh, немного почитайте их. Они не являются частью языка. Есть ли решение, что * IS * часть языка? – user

+0

Файл интерфейса D просто использует другую часть того же языка D. (На самом деле компилятор dmd не заботится о том, является ли расширение .d или .di, все они работают одинаково.) –

ответ

4

Если я пишу D-файл, подобный этому: http://arsdnet.net/dcode/iface/test.d и вы компилируете с помощью dmd -c, вы увидите, что он идет без ошибок; это действительный файл D. Язык позволяет вам писать прототипы функций без реализаций.

Файл .di просто так, у него просто другое имя файла.

После этого main: http://arsdnet.net/dcode/main.d, если вы скомпилируете dmd main, он автоматически выполнит поиск iface/test.d, когда увидит «import iface.test;», найдите этот файл .d или, если вы его переименуете но то же самое, и получите определение интерфейса.

dmd main не работает с ошибкой компоновщика, поэтому нам нужно его реализовать: http://arsdnet.net/dcode/impl.d Примечание: имплант не импортирует модуль, поэтому он никогда не проверяет другой файл. Хранение файлов .di и .d в синхронизации является одной из сложных частей здесь, если вы не создаете автоматически файл интерфейса, поскольку неопределенные методы дадут ошибки компоновщика, но порядок методов важен: он должен соответствовать, и поэтому список переменных, если есть публичные. В противном случае код использования и код реализации не согласуются с макетом класса.

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

Вы также заметите, что в файле реализации также указан класс и т. Д. D не поддерживает синтаксис void MyClass::add(int a) {}. C++ должен написать метод вне класса.

Насколько я знаю, нет способа заставить файл реализации искать заголовок, если вы поместите оба в командной строке, вы получите: «Ошибка: модуль iface.test из файла iface/test.d конфликтует с другим модульным тестом из файла impl.d «

Рекомендуется использовать файлы .di, чтобы их генерировать с помощью dmd -H.Это считывает полный файл реализации и удаляет тела функций, оставляя только определения. Эта часть, вероятно, является ключевым моментом, когда они говорят, что это особенность компилятора - файл .di является допустимым и стандартным D, но сгенерирован с помощью опции компилятора, которая необязательно должна быть частью других компиляторов.

+0

Какова фактическая команда компилятора для компиляции этого примера? –

+0

'dmd main', чтобы увидеть ошибку и' dmd main.d impl.d', чтобы увидеть, как она запускается успешно. Загрузите оба файла в свою папку. –

3

Вы можете объявлять функции без указания их реализации с помощью extern, например .:

extern(D): 
void foo(string name); 

Затем просто предоставить объектный файл/архив с реализацией для связывания. Обратите внимание, что имя модуля является частью искаженного имени функции, так что либо файл заголовка нуждается в том же имени модуля, что и скомпилированный модуль, либо вы можете использовать extern(C) для отключения манипуляции (исключает перегрузку и использует соглашение о вызове C).

+0

Файлы FWIW, .di - это просто автоматизация этого соглашения. – BCS

+0

@BCS И, таким образом, все это становится для меня поучительным. Благодарю вас. – user

3

Адам уже все объяснил. Я просто попытаюсь добавить дополнительный пример:

Скажите, что вы создаете библиотеку под названием mylib и она имеет функции foo() и bar(). Ваш код и библиотеки тестовое приложение может выглядеть следующим образом: при запуске

mylib.d - интерфейс файла

module mylib; 

void foo(); 
void bar(); 

mylib_impl.d - определения здесь

module mylib; 

import std.stdio; 

void foo() { 
    writeln("foo()"); 
} 

void bar() { 
    writeln("bar()"); 
} 

mylib_test .d - испытательная заявка

// To compile: dmd mylib_impl.d mylib_test.d 
// NOTE: we do not compile the "interface" file mylib.d !! 
module mylib_test; 

import mylib; 

int main() { 
    foo(); 
    bar(); 

    return 0; 
} 

Теперь нетрудно понять, что у нас есть .di файлы исключительно для удобства и ясности. Если мы решили использовать файл интерфейса, мы бы переименовали mylib.d в mylib.di и mylib_impl.d на mylib.d. mylib_test.d останется неповрежденным.

+0

как это будет работать с пакетом? –

+0

Пакет - это просто каталог. Он должен работать без изменений. – DejanLekic

Смежные вопросы