【问题标题】:how to automatically generate a unique c++ class based on a file如何根据文件自动生成唯一的 c++ 类
【发布时间】:2021-10-23 01:53:37
【问题描述】:

让我先说我不知道​​我问的问题是否正确。我对 c++ 还很陌生,我还没有完全理解它的所有细微差别,但我已经用其他 OOP 语言编写了近 7 年的代码。

我最初问: 有没有办法获取文本文件并自动生成 C++ 代码?如果是,我该怎么做?有哪些资源可以解释该过程?

但要澄清一下,我真正想要的是: 有没有办法获取文本文件或其他文件类型(如 json)并使用它来生成可与 c++ 交互的已编译 c++ 类或其他已编译对象?

最终结果不需要是人类可读的,它可以是系统特定的。我希望能够在编译时做到这一点。它不必在运行时发生。我会在运行时知道我需要什么类。只是我将要制作的课程(并且会有很多课程)都非常相似,只是在几个关键地方有所不同。所以我想要一种方法告诉计算机重要的东西(可能只需要 5 或 6 行代码),并让它生成其他 30 行样板代码。

我正在制作一个游戏引擎,并且我正在尝试设计一个系统,让我可以即插即用系统,而无需编写大量样板代码。

有人评论说我应该让这个例子更简单。就这样吧。

我正在尝试构建一个系统,该系统接受文本文件输入并为我构建一个已编译的 c++ 二进制文件。它不必是文本文件,也不必是专门的 c++,只要它可以与 c++ 交互(相对容易)。这是为了减少样板代码的数量,以及几乎相同的简短无用 c++ 文件的数量。

例如有一个名为 example.txt 的文件,看起来像这样。

objectGenerator ExampleClass {
autofunction[hello world]
}

然后我希望生成一些功能类似于 c++ 类的东西

class ExampleClass
{
public:
    void callAutoFunctions()
    {
        helloWorld();
    }

private:
    AutoFunction helloWorld;
};

然后在我的 main.cpp 中,例如我可以调用

void main()
{
    GeneratedClasses::ExampleClass exampleClass; 
    exampleClass.callAutoFunctions();
}

打印“hello world”。

我希望能够做到这一点,这样我就可以制作许多不同的游戏对象,我可以轻松地从中提取部分内容(只需更改一两行文本)。这将使迭代游戏创意变得更加容易,从长远来看,这意味着我的游戏不会像往常一样是一堆乱七八糟的参考资料和对简单问题的复杂解决方案。

我不介意我必须用与 c++ 不同的语言编写脚本。如果我现在可以设置它,我的独立游戏设计生涯将会轻松很多,并且可以将它用于我未来的所有游戏。

附言我正在尝试重新制作一年多前在 python 街机中创建的game,但在 c++ 中运行得更好,而且我实际上可以为游戏创建一个 exe 文件,我可以提供给朋友,或者添加到 itch .io。我知道当我用 C++ 编写代码不到一年时,假设我能够制作一个可行的、可销售的游戏是非常大胆的,但我是一个任务驱动的人,我没有动力学习我需要的 c++,而不用做这样的事情。

【问题讨论】:

  • C++ 有模板。
  • 您可以使用脚本来自动生成、编译和喜欢代码。你有什么问题?
  • 我知道模板,但据我所知,我无法对其进行调整。我不知道一个实体会有多少属性。 @Serge 这正是我想知道的。如何自动生成代码。我什至没想过要搜索它,所以谢谢。
  • C++ 是当今使用的最复杂的通用编程语言。在多本 C++ 教科书的指导下,大约需要 3-5 年的学习时间,才能获得对 C++ 基础知识的平均知识和理解:类、方法、继承、多重继承、多态性、重载、容器、算法、多线程、模板、参数包,类型特征等等。而只有扎实掌握了基础知识,才能进入精品领域的研究,比如写一个“游戏引擎”。如果没有扎实掌握基础知识,这总是以眼泪告终。
  • C++ 根本无法以这种方式工作。 C++ 程序中的所有类都是在编译时声明和定义的。类不是可以在运行时临时创建的东西。 “为我构建了一个已编译的 C++ 二进制文件”——这就是 C++ 编译器所做的。我想可以编写一些代码来写出 C++ 源文件,然后运行 ​​C++ 编译器将其编译成可执行文件。但我怀疑这种纸牌屋能撑多久。

标签: c++ game-engine game-development


【解决方案1】:

似乎您想要的只是单独编译。首先,您为您希望使游戏更加解耦的部分制作一个界面:

// Player.hpp

#include <memory>

struct IPlayer {
  virtual void run() = 0;
  virtual ~IPlayer() = default;
};

std::unique_ptr<IPlayer> getPlayer();

然后在你的程序中使用它而不提供实现:

// main.cpp

#include "Player.hpp"

int main() {
  auto player = getPlayer();
  player->run();
}

然后你编译它而不链接:

$ clang++ -c main.cpp -O3 -Wall -Wextra

现在您开始着手实际的实现:

// FastPlayer.cpp

#include "Player.hpp"

struct FastPlayer : IPlayer {
  void run() override { /* ... */ }
}

std::unique_ptr<IPlayer> getPlayer() {
  return std::unique_ptr<IPlayer>{ new FastPlayer };
}

然后编译您现在要测试的任何实现,并将其与您之前编译的二进制文件链接:

$ clang++ FastPlayer.cpp main.o -O3 -Wall -Wextra

通过这种方式,您可以轻松更换实现以测试大量功能。它比在运行时加载任意代码更安全。

理想情况下,您不会手动执行此操作,而是让 CMake 之类的构建系统为您处理。

【讨论】:

    【解决方案2】:

    应用程序构建后(编译并链接到 exe 文件)后,您无法向应用程序添加新类。

    从技术上讲,您可以使用 C 来编写自己的语言,这就是他们制作 Python 或 Java 的方式。如果这是正确的工具,只需使用它们开始。自己写这样的东西需要 400 年。

    可以使用外部二进制文件。您必须在构建期间链接到它们。库通常使用 C 接口,很容易通过唯一的名称找到一个函数并调用它。要使用 c++ 库,您的应用程序和库都必须由相同的 c++ 编译器、相同的编译器版本和设置构建。例如,这对于访问标准库很有用。

    通常您希望避免为自己的应用程序编写库。只需在单个可执行文件中编写任意数量的类,使用不同的参数运行它。

    您可以为游戏、玩家、球等编写类。将之前的状态保存在文件中并再次读取。 cgame 可以有自己的cplayercball 等。这将适合各种情况。

    C++ 没有像 Javascript 这样可以将onclick() 识别为命令的功能。您必须将字符串 "onclick" 保存在一个文件中,读取它、解析它并自己解释它。

    最接近的是保存纯数据结构:

    struct plain_data
    {
        int speed;
        int size;
        int previous;
        //don't put classes and pointers here
    };
    
    plain_data data = { 1,2,3 };
    std::ofstream fout("file.dat", std::ios::binary);
    fout.write((char*)&data, sizeof(data));
    fout.close();
    
    std::ifstream fin("file.dat", std::ios::binary);
    fin.read((char*)&data, sizeof(data));
    fin.close();
    

    编辑

    假设您想要制作像 Halo 或 Doom Eternal 这样的 c++ 游戏。这可以在没有脚本语言的情况下完成。您只需要外部库来处理图像等。

    现在假设您想制作一个可以玩任何游戏的程序。在开发这个程序的时候,你对那个游戏一无所知,它可能是乒乓球,也可能是纸牌游戏或其他东西。这将需要一种脚本语言。

    后者是一项更复杂的任务。这不应该是您在 C++ 开发中的第一次尝试。您可能会考虑使用“即时编译器”的类 Java 语言,它接受文本命令并在运行时将它们转换为二进制文件。

    【讨论】:

    • 编写自己的脚本语言或 DSL 绝对不会“花费 400 年”,它可以在不到一周的时间内轻松完成(JavaScript 是在 10 天内创建的)。为这种语言创建工具是一个不同的问题(以及自定义语言是否是正确的解决方案)
    • @UnholySheep 那是原始的 Javascript,有几个函数,它没有类。要编写一种具有 Java 或 Python 效率的脚本语言,以及它们的功能,我认为需要 400 年。这是基于意见的,我真的不知道。
    • 谢谢!我认为我正在寻找的是您所说的外部二进制文件。我很清楚我不能在运行时这样做,但我不想这样做。我从中得到的是,我必须编写自己的(非常简单的)DSL,我将其解释为外部二进制文件,在编译时链接到我的程序。我什至想要这样做的原因是我的游戏中的任何东西都是通用的。从技术上讲,如果我愿意,我可以通过简单地更改另一个文件中的一行并编译它来将玩家移动脚本放在随机树上。
    • 我编辑了答案,也许它变得更清楚了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-24
    相关资源
    最近更新 更多