在我的面向对象的c ++课程中,我们必须编写下面的这个类。
Point
class Point{
public:
Point( double x = 0, double y = 0 );
double getX() const;
double getY() const;
Point & setX( double x ); // mutator, returning reference to self
Point & setY( double y );
const Point & output() const;
double distance( const Point & other ) const;
private:
double xPoint, yPoint;
}; // class Point
我的问题是......我找不到有关函数setX,setY和输出应该如何工作的任何信息。它们与类本身的类型相同,我写了下面我希望它们的样子。任何人都可以告诉我我做错了什么,也许还有一些关于这些功能如何运作的细节? setX函数应该更改对象中的xPoint,setY应该对yPoint执行相同的操作,输出应该只输出它们。
Point & Point::setX( double x )
{
xPoint = x;
}
Point & Point::setY( double y )
{
Ypoint = y;
}
const Point & Point::output() const
{
cout << xPoint << yPoint;
}
答案 0 :(得分:3)
只需在setX和setY的末尾添加return *this;
:您将返回对象的引用,例如,您可以执行:p0.setX(1.23).setY(3.45)
,当然{{1} Point的一个实例。在输出函数中,在xPoint和yPoint之间放置一个分隔符,就像一个空格。你说p0
:不要将变量类型与函数/方法返回的类型混淆:方法They are the same type as the class itself
,setX
和setY
返回对实例的引用他们所属的班级。请注意,输出返回的引用为output
,因此您可以执行以下操作:
const
但不是:
p0.setX(1.23).setY(3.45).output();
由于p0.output().setX(1.23);
不是const方法(它没有声明它不会修改它所属的类实例中的数据)。
您可以致电:
setX
因为double x = p0.output().getX();
是一个const方法。
注意:我并不是说你应该以这种方式使用这些方法,但重点是展示你可以做些什么。
答案 1 :(得分:0)
Setter是公共元文件,允许您更改类的私有成员,它们没有返回类型,因此setX
,setY
应该是void
而不是Point
:
void set(double x); // Declaration
void Point::setX( double x ) // Definition outside Point.h
{
xPoint = x;
}
与output
相同应该是void
,休息很好你可以定义它,无论你想要显示它,你可以改变它:
void Point::output() const
{
cout << "(" << xPoint << ", " << yPoint << ")";
}
答案 2 :(得分:0)
setX()
可能会更改pointX
成员的值,并返回对正在执行的对象的引用。
所以实现可能类似于
Point &Point::setX(double xval)
{
if (IsValid(xval)) pointX = xval; // ignore invalid changes
return *this;
}
这可以(假设正确使用其他成员函数和运算符)可以在这样的事情中使用
#include <iostream>
// declaration of Point here
int main()
{
Point p;
std::cout << p.setX(25).setY(30).getX() << '\n';
}
虽然这个例子不是特别有用(它显示了可能的),但成员函数调用的链接在各种情况下都很有用。例如,这种技术实际上是iostream
插入和提取操作符工作的基础,并允许在单个语句中插入/提取多个内容。
答案 3 :(得分:0)
setX
和setY
函数的文档说明
// mutator, returning reference to self
您的实现执行变异,但您未能完成此函数应该满足的契约:它应该返回对自身的引用。 / p>
this
是指向您正在调用该方法的对象的指针,因此添加该行
return *this;
将完成合同。
这是暂时的,但它可以帮助你理解为什么有人会想要使用这种“奇怪”的设计。
您可能熟悉以
等方式使用的普通作业a = b = 0;
if((result = some_function()) == 0) {
// Do something in the `result == 0` case
} else {
// Do something in the `result != 0` case
}
和其他类似的事情。第一个示例将a
和b
都设置为0
。第二个示例将函数调用的返回值存储到变量result
中,然后根据该值是否为0
进行分支。
这样做的方式是x = y
是二元运算符,其副作用是将y
的值复制到x
,然后返回该值(技术上是对x
的引用),以便它可以在周围的表达式中使用。
因此,当您编写a = b = 0
时,会将其解析为a = (b = 0)
,并使b
为零,然后计算为a = 0
,然后对其进行评估,使a
为零。同样,对于分支示例。
这是人们在编写代码时喜欢做的事情(这是一个完全独立的主题,无论这是否是好的风格),所以当人们使用operator=
方法设计新类型时,他们会设计它们来支持这种用法,通过使它们返回对分配给的对象的引用。 e.g。
MyClass& MyClass::operator=(arg a)
{
// Copy the value of `a` into this object
return *this;
}
其他赋值运算符(如operator+=
)也可以这样工作。
现在,当您习惯了这种用法时,将它扩展到其他类似于赋值的函数(如setX
和setY
)是一小步。这样可以方便地进行链接修改,如point.setX(3).setY(7)
。