如何根据文件自动生成唯一的c++ class
how to automatically generate a unique c++ class based on a file
让我先说我不知道我问的问题是否正确,以此作为这个问题的开头。我是 c++ 的新手,我还没有完全理解它的所有细微差别,但我已经使用其他 OOP 语言编写了将近 7 年的代码。
我最初问:
有没有办法获取文本文件并自动生成 C++ 代码?如果是,我该怎么做?解释该过程的一些资源是什么?
但要澄清的是,我真正想要的是:
有什么方法可以获取文本文件或其他文件类型(如 json)并使用它来生成编译的 c++ class 或其他可以与 c++ 接口的编译对象?
最终结果不需要是人类可读的,它可以是系统特定的。我希望能够在编译时执行此操作。它不必在 运行 时间发生。我会在 运行 时知道我需要什么 class。只是我将要制作的 classes(而且会有很多)都非常相似,只是在几个关键地方有所不同。所以我想要一种方法来告诉计算机重要的东西(可能只需要 5 或 6 行代码),并让它生成其他 30 行样板代码。
我正在制作一个游戏引擎,我正在尝试设计一个系统,让我可以即插即用系统,而无需编写大量样板代码。
有人评论说我应该让这个例子更简单。就这样吧。
我正在尝试构建一个系统,该系统接受文本文件输入并为我构建一个已编译的 C++ 二进制文件。它不必是文本文件,也不必专门是 c++,只要它可以与 c++ 接口(相对容易)即可。这是为了减少样板代码的数量,以及几乎完全相同的有点无用的短 C++ 文件的数量。
例如,有一个名为 example.txt 的文件,如下所示。
objectGenerator ExampleClass {
autofunction[hello world]
}
然后我希望生成功能类似于 c++ class 的东西,比如
class ExampleClass
{
public:
void callAutoFunctions()
{
helloWorld();
}
private:
AutoFunction helloWorld;
};
然后在我的 main.cpp 中,例如我可以调用
void main()
{
GeneratedClasses::ExampleClass exampleClass;
exampleClass.callAutoFunctions();
}
打印“hello world”。
我希望能够做到这一点,这样我就可以制作许多不同的游戏对象,我可以轻松地从中提取零件(只需更改一两行文本)。这将使迭代游戏创意变得更加容易,并且从长远来看 运行 将意味着我的游戏不再像通常那样是一堆乱七八糟的参考文献和复杂的简单问题解决方案。
我不介意我必须使用与 C++ 不同的语言编写脚本。如果我现在可以设置它,并且将来将它用于我所有的游戏,那将使我的独立游戏设计生涯变得容易得多。
p.s。我正在尝试重新制作我一年多前在 python arcade 中创建的 game,但在 c++ 中它 运行 更好,而且我实际上可以为游戏创建一个 exe 文件我可以送给朋友,或添加到 itch.io。我知道当我用 C++ 编写代码不到一年时,假设我能够制作一款可行的、可销售的游戏是非常大胆的,但我是一个任务驱动的人,我没有动力学习我需要的 c++,而无需像这样做一些过头的事情。
您无法在构建应用程序(编译并linked 到 exe 文件)后向您的应用程序添加新的 类。
从技术上讲,您可以使用 C 编写您自己的语言,这就是他们制作 Python 或 Java 的方式。如果那是正确的工具,就从这些开始。自己写这样的东西需要 400 年。
可以使用外部二进制文件。在构建期间,你必须 link 给他们。库通常使用 C 接口,很容易通过唯一的名称找到一个函数并调用它。要使用 c++ 库,您的应用程序和库都必须由相同的 c++ 编译器、相同的编译器版本和设置构建。例如,这对于访问标准库很有用。
通常您希望避免为自己的应用程序编写库。只需在单个可执行文件中编写尽可能多的 类,运行 它具有不同的参数。
你可以为游戏、球员、球等写类。将之前的状态保存在文件中并再次读取。 cgame
可以有自己的 cplayer
、cball
等。这将适合所有情况。
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 的语言,它接受文本命令并在 运行 时间内将它们转换为二进制文件。
看来你想要的只是单独编译。首先,您为游戏中希望更加解耦的部分创建一个界面:
// 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();
}
然后你编译它没有 linking:
$ 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 };
}
然后编译您现在想要测试的任何实现,并link使用您之前编译的二进制文件:
$ clang++ FastPlayer.cpp main.o -O3 -Wall -Wextra
通过这种方式,您可以轻松更换实现以测试大量功能。它比在 运行 时间加载任意代码更安全。
理想情况下,您不会手动执行此操作,而是让像 CMake 这样的构建系统为您处理。
让我先说我不知道我问的问题是否正确,以此作为这个问题的开头。我是 c++ 的新手,我还没有完全理解它的所有细微差别,但我已经使用其他 OOP 语言编写了将近 7 年的代码。
我最初问: 有没有办法获取文本文件并自动生成 C++ 代码?如果是,我该怎么做?解释该过程的一些资源是什么?
但要澄清的是,我真正想要的是: 有什么方法可以获取文本文件或其他文件类型(如 json)并使用它来生成编译的 c++ class 或其他可以与 c++ 接口的编译对象?
最终结果不需要是人类可读的,它可以是系统特定的。我希望能够在编译时执行此操作。它不必在 运行 时间发生。我会在 运行 时知道我需要什么 class。只是我将要制作的 classes(而且会有很多)都非常相似,只是在几个关键地方有所不同。所以我想要一种方法来告诉计算机重要的东西(可能只需要 5 或 6 行代码),并让它生成其他 30 行样板代码。
我正在制作一个游戏引擎,我正在尝试设计一个系统,让我可以即插即用系统,而无需编写大量样板代码。
有人评论说我应该让这个例子更简单。就这样吧。
我正在尝试构建一个系统,该系统接受文本文件输入并为我构建一个已编译的 C++ 二进制文件。它不必是文本文件,也不必专门是 c++,只要它可以与 c++ 接口(相对容易)即可。这是为了减少样板代码的数量,以及几乎完全相同的有点无用的短 C++ 文件的数量。
例如,有一个名为 example.txt 的文件,如下所示。
objectGenerator ExampleClass {
autofunction[hello world]
}
然后我希望生成功能类似于 c++ class 的东西,比如
class ExampleClass
{
public:
void callAutoFunctions()
{
helloWorld();
}
private:
AutoFunction helloWorld;
};
然后在我的 main.cpp 中,例如我可以调用
void main()
{
GeneratedClasses::ExampleClass exampleClass;
exampleClass.callAutoFunctions();
}
打印“hello world”。
我希望能够做到这一点,这样我就可以制作许多不同的游戏对象,我可以轻松地从中提取零件(只需更改一两行文本)。这将使迭代游戏创意变得更加容易,并且从长远来看 运行 将意味着我的游戏不再像通常那样是一堆乱七八糟的参考文献和复杂的简单问题解决方案。
我不介意我必须使用与 C++ 不同的语言编写脚本。如果我现在可以设置它,并且将来将它用于我所有的游戏,那将使我的独立游戏设计生涯变得容易得多。
p.s。我正在尝试重新制作我一年多前在 python arcade 中创建的 game,但在 c++ 中它 运行 更好,而且我实际上可以为游戏创建一个 exe 文件我可以送给朋友,或添加到 itch.io。我知道当我用 C++ 编写代码不到一年时,假设我能够制作一款可行的、可销售的游戏是非常大胆的,但我是一个任务驱动的人,我没有动力学习我需要的 c++,而无需像这样做一些过头的事情。
您无法在构建应用程序(编译并linked 到 exe 文件)后向您的应用程序添加新的 类。
从技术上讲,您可以使用 C 编写您自己的语言,这就是他们制作 Python 或 Java 的方式。如果那是正确的工具,就从这些开始。自己写这样的东西需要 400 年。
可以使用外部二进制文件。在构建期间,你必须 link 给他们。库通常使用 C 接口,很容易通过唯一的名称找到一个函数并调用它。要使用 c++ 库,您的应用程序和库都必须由相同的 c++ 编译器、相同的编译器版本和设置构建。例如,这对于访问标准库很有用。
通常您希望避免为自己的应用程序编写库。只需在单个可执行文件中编写尽可能多的 类,运行 它具有不同的参数。
你可以为游戏、球员、球等写类。将之前的状态保存在文件中并再次读取。 cgame
可以有自己的 cplayer
、cball
等。这将适合所有情况。
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 的语言,它接受文本命令并在 运行 时间内将它们转换为二进制文件。
看来你想要的只是单独编译。首先,您为游戏中希望更加解耦的部分创建一个界面:
// 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();
}
然后你编译它没有 linking:
$ 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 };
}
然后编译您现在想要测试的任何实现,并link使用您之前编译的二进制文件:
$ clang++ FastPlayer.cpp main.o -O3 -Wall -Wextra
通过这种方式,您可以轻松更换实现以测试大量功能。它比在 运行 时间加载任意代码更安全。
理想情况下,您不会手动执行此操作,而是让像 CMake 这样的构建系统为您处理。