C++中的结构和操作员过载
Structures and Operator Overloading in C++
struct PT
{
double x, y;
PT() {}
PT(double x, double y) : x(x), y(y) {}
PT(const PT &p) : x(p.x), y(p.y) {}
PT operator + (const PT &p) const { return PT(x+p.x, y+p.y); }
PT operator - (const PT &p) const { return PT(x-p.x, y-p.y); }
PT operator * (double c) const { return PT(x*c, y*c ); }
PT operator / (double c) const { return PT(x/c, y/c ); }
};
此代码片段来自 http://stanford.edu/~liszt90/acm/notebook.html#file8 .我无法理解这段代码.有人请解释一下.我知道这是运算符重载,但无法理解运算符重载的确切发生方式。
有人也可以解释这些台词吗:
PT() {}
PT(double x, double y) : x(x), y(y) {}
PT(const PT &p) : x(p.x), y(p.y) {}
结构也有构造函数吗?
double x, y;
声明组成类的两个局部类变量。
PT() {}
默认构造函数。 允许您创建没有任何参数的 PT。
例如 --> PT myObj;
PT(double x, double y) : x(x), y(y) {}
从两个双精度创建点的构造函数。
例如 --> PT myObj(3.5, 9.0);
声明后 --> PT(double x, double y) : x(x), y(y) {}
我们有初始化 .--> PT(Double x, double y) : x(x), y(y) {}
x(x)
相当于this->x = x;
即使用构造函数参数"x"初始化类变量"x"。 他们给参数指定了与类变量相同的名称,这有点令人困惑。 一个更好的例子可能是:
PT(double xInit, double yInit)
: x(xInit)
, y(yInit)
{
}
PT(const PT &p) : x(p.x), y(p.y) {}
复制构造函数以从另一个 PT 对象创建 PT 对象
例如 --> PT myOtherObj(myObj);
PT operator + (const PT &p) const { return PT(x+p.x, y+p.y); }
PT operator - (const PT &p) const { return PT(x-p.x, y-p.y); }
加法和减法运算符得到两点的总和或差,以做第三个点。
例如 -->
PT sumObj = myObj + myOtherObj;
PT diffObj = myObj - myOtherObj;
PT operator * (double c) const { return PT(x*c, y*c ); }
PT operator / (double c) const { return PT(x/c, y/c ); }
乘法和除法运算符,用于将点乘以(或除以)一个常量。
例如 -->
PT prodObj = myObj * 2.7;
PT divObj = myObj / 8.0;
4 行和第 5 行是构造函数,语法x(x)
突出显示了一种调用成员变量构造函数的惯用方法(可以说是向下传递)。
请注意,形式参数不需要不同的标识符。从构造函数主体内部赋值需要不同的命名,因为形式参数"隐藏"了成员变量。即我们需要,例如
PT(double x_, double y_) { x = x_; y = y_; }
另请注意,这样我们不是调用成员 x 的构造函数,而是调用赋值运算符。POD 数据没有区别,但语法允许在类(如 PT
)上使用任意的、用户定义的成员函数。
每当编译器遇到表单调用时
a + b;
它实际上调用
a.operator+(b)
如果该方法存在于 或 的类型中
operator+(a,b)
如果存在这样的自由函数。
运算符???语法只是说您当前正在重载所述运算符???(当然,对于任何有效的???)。
运算符重载是一个概念,其中通常的运算符如 +
、'- , '*
、...对于结构/类也是"重载"的。通常,此工具仅适用于原始数据类型,如int
、double
、....
在struct PT
中,运算符方法被简单地定义。一旦您声明了PT
的对象并开始使用它,它就会启动。例如
PT pt1, pt2;
PT pt3 = pt1 + pt2; // pt1.operator +() has instantiated
通过查看它的非成员版本,可能更容易理解运算符重载。如果要告诉编译器添加两个PT
对象是什么意思,可以编写以下内容:
PT operator + (const PT& a, const PT& b)
{
return PT(a.x + b.x, a.y + b.y);
}
上面的代码只是说,当编译器找到表达式a + b
a
和b
都是PT
实例时,结果是由该函数计算的新PT
实例。
您可以对其他一些运算符执行相同的操作,因此,您可以使您的类实例相对于普通数学的行为更加"自然"。
您拥有的代码是相同的,但以有点不自然的非对称形式编写,例如,您描述了当另一个对象添加到this
对象时该怎么做。对于二进制数学运算符来说,这种方法看起来很奇怪,因为例如,加法的第一个或第二个操作数没有什么特别的,它们都处于相同的逻辑级别。然而,this
概念的不对称性是C++DNA的一部分,你对此无能为力。从理论上讲,对于任何仅采用参数的方法来说,这都是一个糟糕的不对称性,但在实践中,即使使用这种方法,您仍然可以使用相当长的一段时间。
代码的其他部分是:
// Default constructor. Will create an object without any parameter
// and the x, y values will be uninitialized. This is generally a bad
// practice and you should avoid it unless there are very specific and
// measured performance reasons for doing that.
// Having a constructor accepting no parameters is sometimes necessary
// if you want for example to be able to put your instances in an std::vector
// and you may need to call .resize() on the vector. Even if you will always
// just shrink the vector the compiler will require anyway a default
// constructor because there's no shrink-only call on vectors and any
// resize operation is assumed to be potentially growing the size.
PT() {}
// Copy constructor. This is totally unneeded... when you don't
// put a copy constructor in a class the C++ compiler will automatically
// generate exactly this code (i.e. a constructor that will copy-construct
// all members). In general this may be or may not be the right thing
// depending on the class, but in this case is exactly what you want
// and there was no need for this code.
// As a general rule if you see a copy constructor, an assignment operator
// or a destructor but you don't see all three of them in a class then
// most probably there's something wrong. It's difficult to think to
// a real use case in which you need some of them but not all three of
// them... in this case for example the mistake is that this code could
// and should have been omitted.
PT(const PT &p) : x(p.x), y(p.y) {}
- 如何循环打印顶点结构
- 通过方法访问结构
- 使用不带参数的函数访问结构元素
- 预处理器:插入结构名称中的前一个行号
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 孤立代码块在结构中引发异常
- 有什么方法可以遍历结构吗
- 如何在 C# 中映射双 C 结构指针?
- 如何在C++中使用结构生成映射
- 无法将结构注册为增强几何体3D点
- 如何在结构内使操作员<<过载
- 在使用新操作员和C 中的结构的调用构造函数时,获得内存损坏(Malloc)
- 超载结构操作员在乘以双打时会失去精度
- 如何在模板结构中调用操作员
- 如何解决嵌入结构内嵌入的操作员中的歧义
- 如何为结构/类字符串实现比较操作员
- 为什么我不能将该操作员的过载与结构相同的命名空间
- 操作员>>结构过载?
- C++中的结构和操作员过载
- 操作员重新分配功能/结构返回什么