C++ 虚拟函数如何影响OpenGL中点的生成方式?
我有一个项目,我用点画了一个三角形,它叫做Sierpinski垫圈。为了实现这一点,我使用了一个Vx类来保存x和y值。问题是,如果任何方法是虚拟的,它会抛出不同的值,我想知道为什么虚拟函数如何影响在以下OpenGL代码中生成点的方式? 我的vector类具有以下声明:C++ 虚拟函数如何影响OpenGL中点的生成方式?,c++,opengl,C++,Opengl,我有一个项目,我用点画了一个三角形,它叫做Sierpinski垫圈。为了实现这一点,我使用了一个Vx类来保存x和y值。问题是,如果任何方法是虚拟的,它会抛出不同的值,我想知道为什么虚拟函数如何影响在以下OpenGL代码中生成点的方式? 我的vector类具有以下声明: class Vx { public: float x; float y; Vx(); Vx(const float& value); Vx(const float&
class Vx {
public:
float x;
float y;
Vx();
Vx(const float& value);
Vx(const float& x, const float& y);
Vx(const Vx& v);
float getX() const;
void setX(const float& x);
float getY() const;
void setY(const float& y);
const float operator [] (int i) const;
operator const float* () const;
operator float* ();
float& operator [] (int i);
};
std::ostream& operator<<(std::ostream& os, const Vx v);
Vx operator+(const Vx& p1, const Vx& p2);
Vx operator/(const Vx& p1, const Vx& p2);
Vx类{
公众:
浮动x;
浮动y;
Vx();
Vx(常数浮点和值);
Vx(常数浮点和x、常数浮点和y);
Vx(常数Vx&v);
float getX()常量;
无效设置x(常数浮动和x);
float getY()常量;
void setY(常数浮动&y);
常量浮点运算符[](int i)常量;
运算符常量浮点*()常量;
运算符浮点*();
浮点和运算符[](int i);
};
std::ostream&operator具有虚拟方法的类具有指向VMT
(虚拟方法表)的隐式字段指针。您可以通过打印sizeof(Vx)
来检查它,可以使用虚拟方法,也可以不使用虚拟方法。类和结构的内部表示没有被C++标准指定,并且在编译器之间有所不同,因此,不应将类方法与虚拟方法传递给函数,如“代码> GLBuffelDATABOS/CODE”。 < P>类,用虚方法具有隐式字段指针,指向“代码> VMT < /COD>(虚方法表)。您可以通过打印sizeof(Vx)
来检查它,可以使用虚拟方法,也可以不使用虚拟方法。类和结构的内部表示没有被C++标准指定,编译器之间也有不同,因此,在某些研究之后,不应该将类方法与虚拟方法传递到诸如“代码> GLPuffelDATABOS/COD>”之类的函数。我发现了这个问题的更详细的答案,因为它解释了为什么虚拟函数影响类成员有不同的内存分配,导致不同的结果,此外还有一些C++引用的文档,这些文档也解释了多态对象和内存分配。
事实上,这是一种未定义的行为,下面问题的答案用一种简短而更好的方式解释了原因
<> P>还想从下面2个链接中添加C++引用的内容:
我们可以从以下位置找到下一个文档:
多态对象:声明或继承的类类型的对象
至少有一个虚拟函数是多态对象。在每个
多态对象,实现存储附加信息
(在每个现有实现中,除非经过优化,否则它是一个指针
out),它由虚拟函数调用和RTTI功能使用
(dynamic_cast和typeid)在运行时使用
无论使用的是哪种表达式,都是创建对象的对象
在里面对于非多态对象,值的解释是
根据使用对象的表达式确定,并且
在编译时决定
内存位置:内存位置是标量类型的对象
(算术类型、指针类型、枚举类型或std::nullptr\t)
或长度非零的位字段的最大连续序列
注意:语言的各种特性,例如引用和虚拟
函数,可能涉及不可用的其他内存位置
可供程序访问,但由实施部门管理
考虑到所有这些,我们可以更详细地了解使用虚拟函数的未定义行为的来源,了解它们在生成点时如何改变行为。经过一些研究,我发现了这个问题的更详细的答案,因为它解释了为什么虚拟函数影响类成员有不同的内存分配,导致不同的结果,此外还有一些C++引用的文档,这些文档也解释了多态对象和内存分配。
事实上,这是一种未定义的行为,下面问题的答案用一种简短而更好的方式解释了原因
<> P>还想从下面2个链接中添加C++引用的内容:
我们可以从以下位置找到下一个文档:
多态对象:声明或继承的类类型的对象
至少有一个虚拟函数是多态对象。在每个
多态对象,实现存储附加信息
(在每个现有实现中,除非经过优化,否则它是一个指针
out),它由虚拟函数调用和RTTI功能使用
(dynamic_cast和typeid)在运行时使用
无论使用的是哪种表达式,都是创建对象的对象
在里面对于非多态对象,值的解释是
根据使用对象的表达式确定,并且
在编译时决定
内存位置:内存位置是标量类型的对象
(算术类型、指针类型、枚举类型或std::nullptr\t)
或长度非零的位字段的最大连续序列
注意:语言的各种特性,例如引用和虚拟
函数,可能涉及不可用的其他内存位置
可供程序访问,但由实施部门管理
考虑到所有这些因素,我们可以更详细地了解使用虚拟函数的未定义行为的来源,了解它们在生成点时如何改变行为。虚拟
函数不太可能是问题所在,考虑到您显示的代码,因为您似乎没有使用任何间接寻址(例如,通过指向基的指针或引用调用派生类的函数)。更可能的问题是,您将x
和y
成员视为数组的一部分,而它们不是数组的一部分,这将导致未定义的行为。我建议去掉operator[]
和operator float*
Vectors::Vx::Vx() : x(0), y(0)
{
}
Vectors::Vx::Vx(const float& value) : x(value), y(value)
{
}
Vectors::Vx::Vx(const float& x, const float& y) : x(x), y(y)
{
}
Vectors::Vx::Vx(const Vx& v) : x(v.x), y(v.y)
{
}
float Vectors::Vx::getX() const
{
return this->x;
}
void Vectors::Vx::setX(const float& x)
{
this->x = x;
}
float Vectors::Vx::getY() const
{
return this->y;
}
void Vectors::Vx::setY(const float& y)
{
this->y = y;
}
float& Vectors::Vx::operator[](int i)
{
return *(&x + i);
}
const float Vectors::Vx::operator[](int i) const
{
return *(&x + i);
}
Vectors::Vx::operator const float* () const
{
return static_cast<const float*>(&x);
}
Vectors::Vx::operator float* ()
{
return static_cast<float*>(&x);
}
std::ostream& Vectors::operator<<(std::ostream& os, const Vx v)
{
os << "Vx: " << "x = " << v.x << ", y = " << v.y << std::endl;
return os;
}
Vx Vectors::operator+(const Vx& p1, const Vx& p2)
{
return Vx(p1.x + p2.x, p1.y + p2.y);
}
Vx Vectors::operator/(const Vx& p1, const Vx& p2)
{
return Vx(p1.x / p2.x, p1.y / p2.y);
}
void sierpinskiGasket() {
using namespace Vectors;
/*
Creamos la informacion para el triangulo
*/
const int numPoints = 5000;
Vx points[numPoints];
points[0] = Vx(0.0f, 0.0f);
Vx vertices[] = {
Vx(-0.50f, -0.50f),
Vx(0.50f, -0.50f),
Vx(0.0f, 0.50f)
};
for (int i = 1; i < numPoints;i++) {
int j = rand() % 3;
points[i] = (points[i - 1] + vertices[j]) / 2;
}
/*
Generamos el buffer para el triangulo
*/
unsigned int triangle_vbo;
glGenBuffers(1, &triangle_vbo);
glBindBuffer(GL_ARRAY_BUFFER, triangle_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
}