Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C+中键入别名+;_C++ - Fatal编程技术网

C++ 在C+中键入别名+;

C++ 在C+中键入别名+;,c++,C++,我有一个classPoint和一个classRect。我希望有两个用于Rect的构造函数:一个带有点和维度(宽度、高度),另一个带有两个点(左上、右下)。现在,事实证明,点也可以被看作一个维度,因此我不想创建维度类,而是想使用我的点,基本上如下所示: class Point{...}; typedef Dimension Point; class Rect{ public: Rect(Point, Point); Rect(Point, Dimensio

我有一个class
Point
和一个class
Rect
。我希望有两个用于
Rect
的构造函数:一个带有
点和维度(宽度、高度),另一个带有两个点(左上、右下)。现在,事实证明,
也可以被看作一个维度,因此我不想创建
维度
类,而是想使用我的
,基本上如下所示:

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

class Rect{
    public:
        Rect(Point, Point);
        Rect(Point, Dimension);
}
enum CoordinateSystem {
  Geographic,
  Cartesian
};

template<CoordinateSystem C>
struct Point {
  double x,y;
};

double distance(Point<Cartesian>, Point<Cartesian>);
double distance(Point<Geographic>, Point<Geographic>);
所以问题是:编译器在
维度
之间有区别吗?我试过了,消息是“重载Rect(Point,Point)的调用是不明确的”

我该怎么做?最好没有继承:)

编辑

我现在明白了,这对编译器来说是一样的。但我需要的是另一种情况

我有道理。坐标可以是carthesian系统(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

我知道它不是那样工作的。但是这个问题的答案也是“创建两个类”吗?

你应该创建一个不同类型的
维度。是的,
可用于指定尺寸,但这并不意味着使用相同的类型是有意义的。

一个快速解决方案是,您可以有一个构造函数,并找出在其逻辑中提供的类。

编译器对
维度
没有区别


您必须为
维度
创建另一个类。作为提示,您可以对其成员使用
w
h
而不是
x
y

虽然维度和点的相似之处在于它们都可以实现为一对数字,但它们的行为并不相同,例如,维度可能具有高度()和宽度()等成员函数而点可能有x()和y()。因此,您不应该将它们设置为相同的,而应该为每个类设置不同的类。

对于编译器,所有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!
};

或者更好地使用空类作为:

//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;
//空类
结构点arg{};
结构维度arg{};
结构SizeArg{};
模板
类类型{/*…*/};
类型定义类型点;
类型定义类型尺寸;
类型定义类型大小;

这是许多C++库采用的最后一种方法,如Boosi.

< P>可以尝试从点继承维度继承而不是TyBuff::BR>
类维度:公共点{}


而且,将对象类型作为副本传递是低效的;而是将它们作为常量引用传递。这还有一个额外的好处,就是允许编译器为这些类型生成多态代码。

如果
维度
没有相同的行为,那么您的
类型定义
就是一个逻辑错误。如果有,那么您不需要两个构造函数


回应你的编辑

对于您提供的示例,您有两个类,它们存储相同数量的数据,但具有不同的行为。
std::size\u t
void*
是一个很好的例子——它们对于底层硬件来说都是相同的位数,但是语言的类型系统赋予它们完全不同的含义

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

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

class Rect{
    public:
        Rect(Point, Point);
        Rect(Point, Dimension);
}
enum CoordinateSystem {
  Geographic,
  Cartesian
};

template<CoordinateSystem C>
struct Point {
  double x,y;
};

double distance(Point<Cartesian>, Point<Cartesian>);
double distance(Point<Geographic>, Point<Geographic>);
enum协调系统{
地理的,
笛卡尔
};
模板
结构点{
双x,y;
};
双距离(点,点);
双距离(点,点);

点和维度与编译器相同。为什么需要两个声明?@bashrc:可能是因为这两种情况下的初始化不同(可以使用两点或一个点及其维度指定矩形-这两种情况下的计算不同).那么为什么typedef指向维度?那么应该为维度添加另一个类?从设计的角度来看,这两个维度对我来说似乎都不一样。JesperE,所以你建议创建一个类或结构维度?@wal-o-mat:视情况而定。尺寸是指尺寸吗?如果是这样,那么是的,全心全意地。进行区分会产生一些额外的代码,但根据我的经验,客户机代码中出现错误的空间要小得多。我甚至会确保使用不同的数据成员(如Didier所建议的w和h),当然也不会在点和大小之间进行隐式转换。复制一个Point类,与虚拟函数相比可能最多8字节?复制这样一个类的开销很小。随着时间的推移和类型的增加,情况会怎样呢?在发现副本是一个瓶颈之后,修改代码将是一项艰巨的任务。这是一个很好的技巧。也可用于Time和TimeDiff等。与boost::multi_index_container类似,我甚至建议使用空类而不是数字来进行更具文档化的区分(类PointType{};类DimensionType{};)@stefaanv:使用空类是个好主意。我认为这看起来很可怕,而且维度和点对象肯定会有不同的成员函数,并且在实现中不会共享太多。在我看来,拥有两个不同的类要简单得多;更易于实现和理解。@ChrisCard:如果
维度
具有不同的成员函数,则OP不会尝试使用不会创建不同类型的
类型定义。所以我的解决方案解决了这个问题。@ChrisCard:。。。另外,如果两种类型的成员不同,除了一些常见的成员之外,还可以这样做:
class Point:public Type{/*…*/}
和类似的
维度
。在这个