[英]Type aliases in C++
我有一个Point
类和一个Rect
类。 我想为Rect
有两个构造函数:一个带有Point
和一个尺寸(宽度,高度)的构造函数,一个带有两个Point(左上,右下)的构造函数。 现在事实证明Point
也可以看作是一个维度,因此与其创建Dimension
类,不如我想使用Point
,基本上是这样的:
class Point{...};
typedef Dimension Point;
class Rect{
public:
Rect(Point, Point);
Rect(Point, Dimension);
}
所以问题是:编译器是否会在Point
和Dimension
之间产生区别? 我尝试过,消息ist“重载Rect(Point,Point)的调用是模棱两可的”。
我该怎么办? 最好没有继承:)
编辑
我现在了解到编译器是相同的。 但是还有另一种需要的情况。
我有一个要点。 坐标可以在笛卡尔系统(x,y)或GPS坐标(lon,lat)中。 对我来说,调用组件x0
和x1
所以我只想使用一个类。
现在我要计算两点之间的距离,我的想法如下:
typedef PointLonLat Point;
typedef PointXY Point;
double distance(PointLonLat, PointLonLat);
double distance(PointXY, PointXY);
PointLonLat p1(10, 10);
PointLonLat p2(11, 11);
double dist = distance(p1, p2); // the correct implementation is used
我知道它不是那样工作的。 但是,答案是否还会是“两堂课”?
所有类型定义对于编译器都是相同的。
你可以这样做:
//class template to be used to generate different class types!
template<int>
class Type{ /*...*/ };
//instantiate different class types, each with different template argument
typedef Type<0> Point;
typedef Type<1> Dimension;
typedef Type<2> Size;
class Rect{
public:
Rect(Point, Point);
Rect(Point, Dimension); //its a different constructor!
};
使用这种方法,您可以在类模板Type
创建不同的类型。
除了整数文字,您可以将命名枚举用作:
enum TypeArg
{
PointArg,
DimensionArg,
SizeArg
};
template<TypeArg>
class Type{ /*...*/ };
typedef Type<PointArg> Point;
typedef Type<DimensionArg> Dimension;
typedef Type<SizeArg> Size;
甚至最好将空类用作:
//empty classes
struct PointArg{};
struct DimensionArg{};
struct SizeArg{};
template<typename T>
class Type{ /*...*/ };
typedef Type<PointArg> Point;
typedef Type<DimensionArg> Dimension;
typedef Type<SizeArg> Size;
许多C ++库(例如Boost)都采用了最后一种方法。
您应该使Dimension
为其他类型。 是的,可以使用Point
来指定尺寸,但这并不意味着使用相同的类型是有意义的。
编译器在Point
和Dimension
之间没有区别。
您必须为Dimension
创建另一个类。 只是提示,您可以使用w
和h
代替x
和y
作为其成员。
如果point
和dimension
行为不同,则您的typedef
是逻辑错误。 如果他们这样做,则您不需要两个构造函数。
回应您的编辑
对于您提供的示例,您拥有的两个类存储相同数量的数据,但行为不同。 这与std::size_t
和void*
完全不同-它们对于底层硬件来说都是相同的位数,但是语言的类型系统赋予它们完全不同的含义。
您的示例可以通过使用两个不同的类或通过使用模板类来避免重复来解决,例如:
enum CoordinateSystem {
Geographic,
Cartesian
};
template<CoordinateSystem C>
struct Point {
double x,y;
};
double distance(Point<Cartesian>, Point<Cartesian>);
double distance(Point<Geographic>, Point<Geographic>);
一种快速的解决方案是,您可以有一个构造函数,并弄清楚逻辑内部提供的类
尽管Dimension和Point是相似的,因为它们都可以实现为一对数字,但是它们的行为并不相同,例如Dimension可能具有height()和width()之类的成员函数,而Point可能具有x()和Y()。 因此,您不应该使它们相同,但是每个类具有不同的类。
您可以尝试使Dimension从Point继承,而不是成为typedef:
class Dimension : public Point {}
同样,将对象类型作为副本传递效率很低。 而是将它们作为常量引用传递。 这具有允许编译器为那些类型生成多态代码的额外好处。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.