C ++ условное включение файла времени выполнения - PullRequest
5 голосов
/ 19 января 2012

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

#include "lan_eng.h"

Следовательно, игра не позволяет менять язык после компиляции клиента. У меня вопрос, есть ли способ, которым я могу включить файлы условно во время выполнения? Я новичок в C ++, поэтому сначала я подумал, что я мог бы сделать что-то вроде этого:

#define DEF_LANGUAGE_ENG
//#define DEF_LANGUAGE_DEN

#ifdef DEF_LANGUAGE_ENG

    #include "lan_eng.h"

#endif

#ifdef DEF_LANGUAGE_DEN

    #include "lan_den.h"

#endif

Конечно, это облегчает поддержку, но проблема в том, что я считаю, что это работает только во время компиляции. Я хотел бы иметь возможность хранить выбранный язык в переменной (которая изменяется во время выполнения), а затем использовать эту переменную, чтобы выбрать, какой файл заголовка включить. Есть ли способ сделать это с заголовочными файлами, или я буду вынужден создать класс?

Надеюсь, это не глупый вопрос; мои поиски не дали мне результатов, на которые я надеялся.

Заранее спасибо!

Ответы [ 4 ]

5 голосов
/ 19 января 2012

Вы не можете изменять # include во время выполнения, поскольку они оцениваются только во время компиляции.

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

Если вы разрабатываете его таким образом, вы можете хранить все свои «языковые листы» в одной папке, а затем попросить программу проверить эту папку на наличие всех доступных языковых листов. Это позволит пользователям также добавлять языки в вашу программу.

Что вам в основном нужно будет сделать, это создать таблицу строк, что может быть сделано как часть метода с жестким кодом или как часть более динамического метода (упоминаемого как языковые таблицы).

3 голосов
/ 19 января 2012

Возможно, самый простой способ, о котором я подумал:

struct language {
    virtual str::string greeting() =0;
    virtual str::string greeting(const std::string& name) =0;
    virtual str::string goodbye() =0;
    virtual ~language() {}
};
struct English_language {
    virtual str::string greeting() {return "Hello";}
    virtual str::string greeting(const std::string& name) {return "Hello "+name;}
    virtual str::string goodbye() {return "Goodbye";}
} English;
struct German_language {
    virtual str::string greeting() {return "Hallo";}
    virtual str::string greeting(const std::string& name) {return name+" Hallo";}
    virtual str::string goodbye() {return "Auf Wiedersehen";}
} German;
language* CurLanguage = &English;

int main() {
   std::cout << CurLanguage->greeting("Steve") << '\n';
   CurLanguage = &German;
   std::cout << CurLanguage->goodbye() << '\n';
}

[EDIT] Я переписал его с нуля, поскольку понял, что чисто виртуальные функции - это ошибка во время компиляции, если вы пропустите предложение, что значительно упрощает обслуживание. Эта версия также имеет возможность аккуратно обрабатывать переменные (даты, имена, время, числа и т. Д.). Эта концепция основана на том, что мы используем на моей работе, более 2900 фраз / предложений на ~ 20 языках.

3 голосов
/ 19 января 2012

Вы не можете сделать это с #include, это только время компиляции. Более конкретно, это только препроцессор, что происходит перед компиляцией.

Чтобы получить вариацию во время выполнения, вам нужно будет переместить ваши переводы в текстовый файл (возможно, что-то вроде xml, но простой текст тоже работает) и настроить систему, которая загружает файл при запуске, чтобы заполнять строки в код, который нуждается в переводе.

Это также означает, что все ваши строки будут динамически изменяться при запуске, поэтому период инициализации для кода увеличится. Но иногда это цена гибкости.

0 голосов
/ 19 января 2012

Предварительная обработка (#include, #ifdef, #define и т. Д.) Фактически происходит ДО компиляции. Вы можете думать о предварительной обработке как о замене текста, результатом которого является исходный код, передаваемый компилятору. #defines и тому подобное занимают отдельное пространство имен от переменных в вашей программе, и к тому времени, когда ваша программа компилируется, все это уже в камне. Другими словами, то, что вы просите, НЕ возможно.

Чтобы лучше понять это, посмотрите на параметры вашего компилятора и найдите параметр, который позволит вам сохранить предварительно обработанный вывод.

Вместо этого вам нужно изменить способ обработки строк. Вместо того, чтобы менять строки во время компиляции, вам нужно что-то делать во время выполнения.

Проверьте вашу платформу - на большинстве платформ есть API для локализации. Однако они различаются в зависимости от платформы, поэтому, если вы создаете кроссплатформенное приложение, вам, возможно, придется развернуть свое собственное.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...