在C ++中键入别名

时间:2011-12-08 08:15:18

标签: c++

我有一个班级Point和一个班级Rect。我希望Rect有两个构造函数:一个具有Point和一个维度(宽度,高度),另一个具有两个点(左上角,右下角)。现在事实证明Point也可以看作是维度,因此我想使用Dimension而不是创建Point类,基本上就是这样:

class Point{...};
typedef Dimension Point;

class Rect{
    public:
        Rect(Point, Point);
        Rect(Point, Dimension);
}

所以问题是:编译器是否会对PointDimension产生影响?我试过了,消息是“调用重载的Rect(Point,Point)是不明确的。”

我该怎么做?最好不要继承:)

修改

我现在明白了它与编译器是一样的。但还有另一种情况我需要它。

我有一个点。坐标可以是卡特彼勒系统(x,y)或GPS坐标(lon,lat)。我完全可以调用组件x0x1,所以我只想使用一个类。

现在我想计算两点之间的距离,我的想法如下:

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

我知道这不起作用。但是答案也是“两课”吗?

7 个答案:

答案 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)

编译器在PointDimension之间没有区别。

您必须为Dimension创建另一个类。作为提示,您可以为其成员使用wh代替xy

答案 3 :(得分:1)

如果pointdimension没有相同的行为,那么您的typedef是一个逻辑错误。如果他们这样做,那么你不需要两个构造函数。


回复您的修改

对于您提供的示例,您拥有的是两个存储相同数据量但行为不同的类。它与std::size_tvoid*类似 - 它们与底层硬件的位数相同,但语言的类型系统赋予它们完全不同的含义。

您的示例可以通过使用两个不同的类来解决,或者通过使用模板类来避免重复,如下所示:

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 {}
而且,将对象类型作为副本传递是低效的;将它们作为常量引用传递。这样做的另一个好处是允许编译器为这些类型生成多态代码。