C++ 具有数组成员的结构

C++ 具有数组成员的结构,c++,arrays,opengl,struct,C++,Arrays,Opengl,Struct,我有Material struct,它存储三个阵列:环境光、漫反射和镜面反射。 我用它来存储单个对象的材质信息。 头文件: struct Material { float (&ambient)[4], (&diffuse)[4], (&specular)[4]; Material(float (&ambient)[4], float (&diffuse)[4], float (&specular)[4]); float* Ambient

我有Material struct,它存储三个阵列:环境光、漫反射和镜面反射。 我用它来存储单个对象的材质信息。 头文件:

struct Material
{
  float (&ambient)[4], (&diffuse)[4], (&specular)[4];
  Material(float (&ambient)[4], float (&diffuse)[4], float (&specular)[4]);
  float* Ambient();
  float* Diffuse();
  float* Specular();
}
源文件:

Material::Material(float (&_ambient)[4], float (&_diffuse)[4], float (&_specular)[4]): ambient{_ambient}, diffuse{_diffuse}, specular{_specular}{}

float* Material::Ambient()
{
  return ambient;
}

float* Material::Diffuse()
{
  return diffuse;
}

float* Material::Specular()
{
  return specular;
}
我有此函数来初始化对象:

float random(float min, float max)
{
  return min + static_cast<float> (rand()) / static_cast<float> (RAND_MAX / (max - min));
}

void createBall(int)
{
  float ambient[] = {random(0, 1), random(0, 1), random(0, 1), 1};
  float diffuse[] = {random(0, 1), random(0, 1), random(0, 1), 1};
  float specular[] = {random(0, 1), random(0, 1), random(0, 1), 1};
  (...)
  ballMaterials.push_back(Material(ambient, diffuse, specular));
}

有些事情是非常错误的,因为球是平的和红色的,而不是随机的颜色。我猜我以错误的方式实现了struct,但我不确定如何修复它(数组成员)。你能帮我吗

您的原始结构包含对数组的引用(这是符号在成员声明中所做的)。这意味着数组实际上并不存在于结构中。它们在内存中的其他位置,并且该结构包含一个指向它们实际位置的隐藏指针(reference=隐藏指针[但不要告诉任何人])

因此,您的结构只有在实际数组有效时才有效。由于在CreateBall方法中为它们分配了局部变量,因此一旦从该方法返回,结构就不再有效。任何事情都有可能发生

最简单的解决方案是切换到使用
std::array
来声明您的成员。它为您处理所有混乱的细节。如果不想采用这种方法,则必须声明不带符号的成员数组,并将浮点数从参数复制到构造函数中的项中

注:


其他人在评论中指出了这一点。我只是将此整合到一个答案中(注意,如果您发表了一条评论并希望获得代表,请随意发布一条答案,我将删除我的答案。)

我将详细介绍我关于的使用的评论,并向您展示您正试图做的事情的示例,但改用
std::array

#include <array>
#include <vector>

typedef std::array<float, 4> FloatArray4;
struct Material
{
   FloatArray4 ambient, diffuse, specular;
   Material(const FloatArray4& ambient_, const FloatArray4& diffuse_, 
            const FloatArray4& specular_) : ambient(ambient_), diffuse(diffuse_), specular(specular_){}

   FloatArray4& Ambient() { return ambient; }
   FloatArray4& Diffuse() { return diffuse; }
   FloatArray4& Specular() { return specular; }
};

float random(float minVal, float maxVal)
{
   return minVal + static_cast<float> (rand()) / static_cast<float> (RAND_MAX / (maxVal - minVal));
}

std::vector<Material> ballMaterials;

void createBall(int)
{
  FloatArray4 ambient = {{random(0, 1), random(0, 1), random(0, 1), 1}};
  FloatArray4 diffuse = {{random(0, 1), random(0, 1), random(0, 1), 1}};
  FloatArray4 specular = {{random(0, 1), random(0, 1), random(0, 1), 1}};
  ballMaterials.push_back(Material(ambient, diffuse, specular));
}

void drawBall(float radius, Vector3& position, Material material, Rigidbody rigidbody)
{
  glMaterialfv(GL_FRONT,GL_AMBIENT,material.Ambient().data());
  glMaterialfv(GL_FRONT,GL_DIFFUSE,material.Diffuse().data());
  glMaterialfv(GL_FRONT,GL_SPECULAR,material.Specular().data());
}

int main()
{
   createBall(10);
}
#包括

请注意,没有要处理的指针

通过引用传递
std::array
,在返回数组的函数上,返回对现有
std::array
的引用。如果这是另一个要求,您可以添加其他函数来返回
std::array
的副本


另外,请注意允许访问底层数组的
std::array::data()
函数。

引用局部变量使其消失是不好的。尝试复制数组的内容而不是引用。您没有存储三个数组的
Material
struct:您只有存储三个数组引用的struct。使用
std::array
而不是哑浮点数组和浮点指针,您的所有问题都会消失。
#include <array>
#include <vector>

typedef std::array<float, 4> FloatArray4;
struct Material
{
   FloatArray4 ambient, diffuse, specular;
   Material(const FloatArray4& ambient_, const FloatArray4& diffuse_, 
            const FloatArray4& specular_) : ambient(ambient_), diffuse(diffuse_), specular(specular_){}

   FloatArray4& Ambient() { return ambient; }
   FloatArray4& Diffuse() { return diffuse; }
   FloatArray4& Specular() { return specular; }
};

float random(float minVal, float maxVal)
{
   return minVal + static_cast<float> (rand()) / static_cast<float> (RAND_MAX / (maxVal - minVal));
}

std::vector<Material> ballMaterials;

void createBall(int)
{
  FloatArray4 ambient = {{random(0, 1), random(0, 1), random(0, 1), 1}};
  FloatArray4 diffuse = {{random(0, 1), random(0, 1), random(0, 1), 1}};
  FloatArray4 specular = {{random(0, 1), random(0, 1), random(0, 1), 1}};
  ballMaterials.push_back(Material(ambient, diffuse, specular));
}

void drawBall(float radius, Vector3& position, Material material, Rigidbody rigidbody)
{
  glMaterialfv(GL_FRONT,GL_AMBIENT,material.Ambient().data());
  glMaterialfv(GL_FRONT,GL_DIFFUSE,material.Diffuse().data());
  glMaterialfv(GL_FRONT,GL_SPECULAR,material.Specular().data());
}

int main()
{
   createBall(10);
}