c++类成员函数:如何编写这些函数

c++ class members functions: how to write these functions?

本文关键字:函数 何编写 成员 c++      更新时间:2023-10-16

在我的面向对象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和output应该如何工作的信息。它们与类本身的类型相同,我已经在下面写下了我希望它们看起来的样子。有人能告诉我我做错了什么吗?也许还有更多关于这些功能如何工作的细节?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;
}

只需在setX和setY的末尾添加一个return *this;:您将返回对对象的引用,例如,您可以执行以下操作:p0.setX(1.23).setY(3.45),当然p0是Point的实例。在输出函数中,在xPoint和yPoint之间放置一个分隔符,就像一个空格。您说They are the same type as the class itself:不要将变量类型与函数/方法返回的类型混淆:方法setXsetYoutput返回对它们所属类的实例的引用。请注意,输出返回的引用是const,因此可以执行以下操作:

p0.setX(1.23).setY(3.45).output();

但不是:

p0.output().setX(1.23);

因为setX不是一个const方法(它没有声明不会修改它所属的类实例中的数据)。

您可以改为拨打:

double x = p0.output().getX();

因为CCD_ 10是常量方法。

注意:我并不是说你应该以这种方式使用这些方法,但重点是展示你可以做什么。

Setter是允许您更改类的私有成员的公共方法,它们没有返回类型,因此setXsetY应该是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 << ")";
}

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插入和提取运算符工作的基础,并允许在单个语句中向流插入/提取多个内容。

setXsetY函数的文档显示

// mutator, returning reference to self

您的实现执行突变,但您未能完成此函数应该满足的约定:它应该返回对自身的引用

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
}

以及其他类似的事情。第一示例将ab都设置为0。第二个示例将函数调用的返回值存储到变量result中,然后根据该值是否为0进行分支。

其工作方式是x = y是一个二进制运算符,它具有将y的值复制到x中的副作用,然后返回该值(从技术上讲是对x的引用),以便可以在周围的表达式中使用。

因此,当您编写a = b = 0时,它被解析为a = (b = 0),具有使b为零的效果,然后求值为a = 0,然后求值,使a为零。类似于分支示例。

这是人们在编写代码时喜欢做的事情(这是一个完全独立的主题,无论这是否是一种好的风格),所以当人们使用operator=方法设计新类型时,他们会通过让它们返回对指定对象的引用来设计它们以支持这种用法。例如

MyClass& MyClass::operator=(arg a)
{
    // Copy the value of `a` into this object
    return *this;
}

其他赋值运算符,如operator+=,也以这种方式工作。

现在,当您习惯了这种用法时,将其扩展到其他类似赋值的函数(如setXsetY)只是一小步。这具有额外的便利性,使其易于链式修改,如point.setX(3).setY(7)中所述。