我正在用OpenGL c++制作一个小型游戏引擎,我需要制作很多类,如Camera, BatchRenderer, AudioEngine, ParticleEngine, Level, Player, Zombie, Humans等。现在,玩家必须与诸如Camera, BatchRenderer, AudioEngine, ParticleEngine, Level类的级别数据、Zombie, Human等类进行交互。我通过引用来传递它们中的大部分,这些都是在我的主游戏类中初始化的。
/ AudioEngine和ParticleEngine是在主游戏类中创建的,玩家需要播放声音和模拟粒子。TextureID、位置、半径(大小)、旋转、深度和颜色是渲染玩家所需要的。
Player::Player(AudioEngine& a_audioEngine, ParticleEngine& a_particleEngine
GLuint a_textureID, glm::vec2 a_position, float a_radius,
float a_rotation, float a_depth, Color a_color)
{...}
/ LevelData,僵尸,人类来检查是否有玩家在视野中。
void Player::update(Camera& camera, std::vector<std::string>& levelData,
std::vector<Zombie>& zombies, std::vector<Human>& humans,
float deltaTime)
在这里你可以看到有太多的参数被传递给玩家类,并且在未来也需要更多的参数。但是我看到很多人说在一个函数里有两个或三个以上的参数是不好的。而在我的游戏中,有很多类的参数超过了5、6个。
这对于游戏来说是正确的吗,还是说这是一种不好的做法呢,请告诉我如何解决这个问题。
Sorry for bad English.Thank you very much for reading.
有太多的参数是不好的,只有当你在你的程序中经常调用你的函数时才会这样,因为你要付出把你的函数的参数放在堆栈上的代价,加上函数调用的间接性。
如果你不是经常调用这些函数,那么就不要去打包变量。
如果你需要打包变量,你可以直接把它们放入一个 struct
并向函数传递一个单一的参数(通常是一个引用,以避免复制)!
在函数里有太多的参数是不好的,但它不具有可扩展性和简洁性。它导致函数的用户不方便,对你来说也很难维护。你不能在函数中添加或删除参数,这将花费大量的时间来做。还有一点,你也不需要把结构做得太长。如果结构太长的话,可以拆成有意义的结构。
如果你真的很担心,你可以在一个结构中传递参数。就编译器而言,它的效率并不低。
如果你有c++17,你可以为了可读性,用结构化绑定来解包结构。
如果你有c++20,你可以用命名初始化来创建结构。
例如
#include <string>
struct vec {
double x, y, z;
};
struct func_args {
int a;
std::string b;
double c;
vec x , y , z;
};
void foo(std::string const&, vec const&);
void func(func_args const& args) {
// c++17 feature - structured binding (in this case by reference)
auto& [a, b, c, x, y, z] = args;
foo(b, x);
}
// or by value...
void func(func_args&& args) {
auto [a, b, c, x, y, z] = std::move(args);
foo(b, x);
}
void test()
{
// c++20 feature (and gcc extension prior). Named initialisation.
func({ .a = 0, .b = "alien", .c = 0.0,
.x = { -1, 1, 0},
.y = { -1, 1, 0},
.z = { -1, 1, 0}});
auto const args2 = func_args {
.a = 0, .b = "alien", .c = 0.0,
.x = { -1, 1, 0},
.y = { -1, 1, 0},
.z = { -1, 1, 0}};
func(args2);
}
C++看起来一年比一年像javascript:)
使用一个结构体来绑定类似的参数,如
struct Shape {
float a_radius;
float a_rotation;
float a_depth;
Color a_color;
// ...
};
Player::Player(Shape& shape)。