繁体   English   中英

用数组成员构造

[英]Struct with array members

我有Material结构,该结构存储三个数组:环境,漫反射和镜面反射。 我正在使用它来存储有关单个对象的材质的信息。 头文件:

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));
}

和绘图功能:

void drawBall(float radius, Vector3& position, Material material, Rigidbody rigidbody)
{
  (...)
  glMaterialfv(GL_FRONT,GL_AMBIENT,material.Ambient());
  glMaterialfv(GL_FRONT,GL_DIFFUSE,material.Diffuse());
  glMaterialfv(GL_FRONT,GL_SPECULAR,material.Specular());
  glMaterialfv(GL_FRONT,GL_SHININESS,high_shininess);
  glPushMatrix();
  (...)
  glScalef(radius, radius, radius);
  glCallList(index);
  glPopMatrix();
  glutPostRedisplay();
}

发生了很大的错误,因为球是扁平的红色,而不是随机的颜色。 我想我以错误的方式实现了struct,但是我不确定如何解决这个问题(数组成员)。 你可以帮帮我吗?

我将进一步扩展我对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()函数,该函数可访问基础数组。

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

因此,您的结构仅在实际数组有效的情况下才有效。 由于您在CreateBall方法中为它们分配了局部变量,因此从该方法返回后,结构便不再有效。 什么都可能发生。

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

注意:

其他人在评论中指出了这一点。 我只是将其合并为一个答案(请注意,如果您发表了评论之一并想要代表,请随时发布答案,我将删除我的答案。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM