C++ 固有循环依赖性C++;顶点和向量
我有两个类,一个顶点和一个向量,我试图使用操作符来简化生活。如果您检查下面介绍的vector和vertex类,我将尝试在vertex和vector中实现操作符 比如说 VertexA+VertexB=VectorC//使用的不多 VertexA VertexB=VectorC//可以非常频繁地使用 VertexA+VectorB=VertexC//可以非常频繁地使用 VertexA VectorB=VertexC//可以非常频繁地使用 VectorA+VectorB=VectorC//已使用 VectorA VectorB=VectorC//已使用 VectorA+VertexB=VertexC//已使用 VectorA VertexB=VertexC//已使用 如果您注意到有一个循环依赖项。为了使一个类的运算符按值返回(而不是按引用或指针) 我知道有一种方法,将顶点表示为向量。然而,我想知道是否有不同的解决方案,因为我喜欢这两个不同的类只是为了清楚C++ 固有循环依赖性C++;顶点和向量,c++,compiler-construction,C++,Compiler Construction,我有两个类,一个顶点和一个向量,我试图使用操作符来简化生活。如果您检查下面介绍的vector和vertex类,我将尝试在vertex和vector中实现操作符 比如说 VertexA+VertexB=VectorC//使用的不多 VertexA VertexB=VectorC//可以非常频繁地使用 VertexA+VectorB=VertexC//可以非常频繁地使用 VertexA VectorB=VertexC//可以非常频繁地使用 VectorA+VectorB=VectorC//已使用 V
#ifndef decimal
#ifdef PRECISION
#define decimal double
#else
#define decimal float
#endif
#endif
class Vector;
class Vertex{
public:
decimal x,y;
const Vertex operator+(const Vector &other);
const Vertex operator-(const Vector &other);
const Vector operator+(const Vertex &other);
const Vector operator-(const Vertex &other);
};
class Vector{
public:
decimal x,y;
const Vector operator+(const Vector &other) const {
Vector result;
result.x=this->x+other.x;
result.y=this->y+other.y;
return result;
}
const Vector operator-(const Vector &other) const {
Vector result;
result.x=this->x-other.x;
result.y=this->y-other.y;
return result;
}
const Vertex operator+(const Vertex &other) const {
Vertex result;
result.x=this->x+other.x;
result.y=this->y+other.y;
return result;
}
const Vertex operator-(const Vertex &other) const {
Vertex result;
result.x=this->x-other.x;
result.y=this->y-other.y;
return result;
}
decimal dot(const Vector &other) const{
return this->x*other.x+this->y*other.y;
}
const decimal cross(const Vector &other) const{
return this->x*other.y-this->y*other.x;
}
};
为了使这种类型的代码(算术数据类型)易于编写,通常我使用一组称为“运算符重载助手”的模板,如。 结帐 这种方法的优点是操作符的实现是一致的(
operator+=
实现与operator+
实现是一致的,等等)
在您的例子中,如果只实现顶点和运算符+=(常量向量和其他)
,顶点和运算符-=(常量向量和其他)
,向量和运算符+=(常量向量和其他)
,以及向量和运算符-=(常量向量和其他)
;你负责你的第三到第五箱。怎么做
检查此代码:
//Forward declaration needed:
class Vector;
struct Vertex : public dl32AdditionHelper<Vertex , Vector , true>, //The last parameter is used to enable operator+ simmetry. That is, this covers cases 3 and 7.
public dl32SubstractionHelper<Vertex , Vector , false>, //This covers case 4 (Simmetry si not enabled, see note bellow).
{
float x , y;
//For Vertex + Vector = Vertex
Vertex& operator+=(const Vector& other)
{
x += other.x;
y += other.y;
return *this;
}
//For Vertex - Vector = Vertex
Vertex& operator-=(const Vector& other)
{
x += other.x;
y += other.y;
return *this;
}
};
struct Vector : public dl32AdditionHelper<Vector>, //This covers case 5.
public dl32SubstractionHelper<Vector>, //This covers case 6.
{
float x , y;
//For Vector + Vector = Vector
Vector& operator+=(const Vector& other)
{
x += other.x;
y += other.y;
return *this;
}
//For Vector - Vector = Vector
Vector& operator-=(const Vector& other)
{
x += other.x;
y += other.y;
return *this;
}
};
//需要转发声明:
类向量;
struct Vertex:public dl32AdditionHelper,//最后一个参数用于启用运算符+simmetry。也就是说,这包括案例3和案例7。
public dl32substrationhelper,//这包括情况4(未启用Simmetry si,请参见下面的注释)。
{
浮动x,y;
//对于顶点+向量=顶点
顶点和运算符+=(常量向量和其他)
{
x+=其他.x;
y+=其他。y;
归还*这个;
}
//对于顶点-向量=顶点
顶点和运算符-=(常量向量和其他)
{
x+=其他.x;
y+=其他。y;
归还*这个;
}
};
struct Vector:public dl32AdditionHelper,//这包括案例5。
public dl32substrationhelper,//这包括案例6。
{
浮动x,y;
//对于向量+向量=向量
向量和运算符+=(常量向量和其他)
{
x+=其他.x;
y+=其他。y;
归还*这个;
}
//对于向量-向量=向量
向量和运算符-=(常量向量和其他)
{
x+=其他.x;
y+=其他。y;
归还*这个;
}
};
就这些
对称注意:对称属性意味着对于给定的运算符#,运算a#b等于b#a。算术助手使用此功能提供对称运算符。
例如,矩阵代数:m1+m2==m2+m1,因此运算符+(常数矩阵类型_2&m1,常数矩阵类型_1&m2)
被实现为m2+m1
(调用运算符+(常数矩阵类型_1&m1,常数矩阵类型_2&m2)
)。如您所见,对称性不适用于情况8
My helpers实现使用第一个参数的类型作为运算符的返回类型。这就是为什么您的其他案例未被涵盖的原因。但这种情况意味着从向量到顶点或/或反之亦然的转换。如果您修改实现来实现这一点,您的所有案例都可以涵盖。转发声明实际上解决了我的问题。我遇到的编译问题是因为我的函数签名没有以一种不明显的方式正确匹配。顶点是由从原点开始的向量表示的空间位置。许多图书馆只定义一种类型,因为它们的行为方式相同。你们有什么特别的理由需要两者吗?我不明白你们为什么要把顶点加到向量上,反之亦然。你们似乎通过正向声明来实现这一点。您正在寻找第三种解决方案吗?如果您希望清晰而不需要额外的复杂性,可以使用
typedef Vector Vertex
。请使用友元函数运算符而不是成员。对此,我感到抱歉,但我的前向声明有效。事实证明,我有一个不同的问题,它导致了一个编译器错误,使我认为我根本无法做到这一点。但它成功的方式很好。