我有一个班级Point
和一个班级Rect
。我希望Rect
有两个构造函数:一个具有Point
和一个维度(宽度,高度),另一个具有两个点(左上角,右下角)。现在事实证明Point
也可以看作是维度,因此我想使用Dimension
而不是创建Point
类,基本上就是这样:
class Point{...};
typedef Dimension Point;
class Rect{
public:
Rect(Point, Point);
Rect(Point, Dimension);
}
所以问题是:编译器是否会对Point
和Dimension
产生影响?我试过了,消息是“调用重载的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
我知道这不起作用。但是答案也是“两课”吗?
答案 0 :(得分:3)
所有typedef对于编译器都是相同的。
你可以这样做:
//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。
答案 1 :(得分:2)
您应该使Dimension
成为其他类型。是的,可以使用Point
来指定维度,但这并不意味着使用相同的类型是有意义的。
答案 2 :(得分:1)
编译器在Point
和Dimension
之间没有区别。
您必须为Dimension
创建另一个类。作为提示,您可以为其成员使用w
和h
代替x
和y
。
答案 3 :(得分:1)
如果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>);
答案 4 :(得分:0)
一个快速的解决方案是,您可以拥有一个构造函数,并找出其中提供的类的逻辑
答案 5 :(得分:0)
尽管Dimension和Point的相似之处在于它们都可以实现为一对数字,但它们的行为并不相同,例如: Dimension可能有成员函数,如height()和width(),而Point可能有x()和y()。所以你不应该让它们相同,但每个都有不同的类。
答案 6 :(得分:0)
你可以尝试让Dimension继承自Point而不是typedef:
class Dimension : public Point {}
而且,将对象类型作为副本传递是低效的;将它们作为常量引用传递。这样做的另一个好处是允许编译器为这些类型生成多态代码。