c 输入输出流运算符重载_学习c重载输入和输出运算符

本文介绍C++中如何重载输入和输出流运算符,以实现自定义类型的数据输入输出。通过学习,你可以理解并掌握这一关键的C++特性。
摘要由CSDN通过智能技术生成

c 输入输出流运算符重载

One of the first things you do when you are designing and implementing a class is to determine some way to get the data into your class objects and some way to get data out of your objects. Sometimes member functions work well for this, but at other times you want to use the input and output operators like you use with the built-in data types.

在设计和实现类时,要做的第一件事就是确定某种将数据放入类对象的方法以及某种将数据从对象中取出的方法。 有时成员函数可以很好地实现此目的,但有时您希望像使用内置数据类型一样使用输入和输出运算符。

In this article I’m going to show you how to overload the input operator (>>) and the output operator (<<) so that you can use them with your class objects.

在本文中,我将向您展示如何重载输入运算符( >> )和输出运算符( << ),以便可以将其与类对象一起使用。

关于运算符重载的几句话 (A Few Words about Operator Overloading)

C++ is one of the few languages to allow operator overloading. Overloading operators is useful with classes because there are times when you want to use a class object with an operator that does not recognize that object. This will be true for all your user-defined types (classes).

C ++是少数允许运算符重载的语言之一。 重载运算符对类很有用,因为有时您想将类对象与无法识别该对象的运算符一起使用。 所有用户定义的类型(类)都是如此。

For an example, consider a class called IntData. This class is a wrapper class for integers that includes (hypothetically) some functionality not found in the int type itself. If I want to add two IntData objects together, without operator overloading I will have to provide a member function for doing this. Here is an example code fragment:

例如,考虑一个名为IntData的类。 此类是整数的包装器类,该类包括(假设)包括int类型本身未提供的某些功能。 如果我想将两个IntData对象一起添加而没有操作符重载,则必须提供一个成员函数来执行此操作。 这是一个示例代码片段:

IntData d1(1);
IntData d2(2);
IntData d3 = d1.add(d2);

What I would rather do is this:

我宁愿这样做:

IntData d1(1);
IntData s2(2);
IntData d3 = d1 + d2;

I cannot do this without operator overloading because the + operator is not defined to work with my IntData objects. With operator overloading, on the other hand, I can have the + operator recognize my IntData objects and perform the resulting addition. This makes operator overloading an important part of many class definitions.

没有运算符重载,我无法做到这一点,因为+运算符未定义为与我的IntData对象一起使用。 另一方面,通过运算符重载,我可以让+运算符识别我的IntData对象并执行结果加法。 这使得运算符重载是许多类定义的重要组成部分。

This also applies to operations such as input and output. I can’t simply write this to display the contents of an IntData object:

这也适用于输入和输出等操作。 我不能简单地编写以下代码来显示IntData对象的内容:

cout << d1 << endl;

The << operator has no knowledge of my class definition. Nor can I use the input operator to put data into an IntData object:

<<操作符不了解我的类定义。 我也不能使用输入运算符将数据放入IntData对象:

cin >> d2;

To allow these operations to work so that the users of my class can use these objects in the same manner they use primitive data types, I need to overload the input and output operators to recognize IntData objects.

为了使这些操作起作用,以便类的用户可以使用与使用原始数据类型相同的方式使用这些对象,我需要重载输入和输出运算符以识别IntData对象。

重载初步:朋友功能 (Overloading Preliminary: Friend Functions)

To properly overload operators to work with classes, you must define the function that overloads the operator as a friend function. A friend function is a function that has access to the private member variables of a class. The function is not considered part of the class; it just has access to the private member variables of the class to perform its function.

要适当地重载运算符以使用类,您必须将重载该运算符的函数定义为friend function 。 朋友函数是可以访问类的私有成员变量的函数。 该功能不属于该类; 它只能访问该类的私有成员变量以执行其功能。

Here is a simple example using a definition of the IntData class I discussed above. To more realistically demonstrate how friend functions work, I need to split the declaration of the class out from the definition of the class, though I am going to keep them both in the same file for readability sake. Here is the declaration and definition of the IntData class:

这是一个使用上面讨论的IntData类的定义的简单示例。 为了更真实地展示友善函数的工作方式,我需要将类的声明与类的定义分开,尽管为了便于阅读,我将它们都保留在同一文件中。 这是IntData类的声明和定义:

class IntData {
private:
int data;public:
IntData(int);
friend void print(const IntData &);
};IntData::IntData(int d) {
data = d;
}void print(const IntData &d) {
cout << d.data;
}

You can see that the print function is defined in the class definition but is not really part of the class. I can’t access it from an IntData object using the dot operator. If I try I get an error. Instead, I use it like a regular function and pass an IntData object to it. Here is a sample program to demonstrate how to use the friend function:

您可以看到print函数是在类定义中定义的,但实际上并不是该类的一部分。 我无法使用点运算符从IntData对象访问它。 如果尝试,会出现错误。 相反,我将其像常规函数一样使用,并将IntData对象传递给它。 这是一个示例程序,以演示如何使用friend函数:

int main ()
{
IntData d1(12);
print(d1); // displays 12
return 0;
}

There is, of course, more to friend functions than what I’ve shown here but this is enough to get you through this article on operator overloading. I will cover the details of friend functions, and friend classes, in a separate article.

当然,与朋友功能相比,我在这里展示的功能更多,但这足以使您了解这篇有关运算符重载的文章。 我将在另一篇文章中介绍朋友功能和朋友类的详细信息。

重载输出运算符 (Overloading the Output Operator)

I’ll start my overloading demonstration by overloading the output operator (<<) to work with a Point class that I’ve defined. Here is the simple class definition for Point:

我将通过重载输出运算符( << )以与我定义的Point类一起工作来开始重载演示。 这是Point的简单类定义:

class Point {
private:
int x, y;
public:
Point(int, int);
};

First, let’s discuss how the output operator is overloaded. Overloading an operator involves creating a function definition that extends the definition of what data types the operator can work with. The function looks like a regular function. It has a return type, a name (the operator itself), a parameter list, a function body, and a return value.

首先,让我们讨论输出运算符是如何重载的。 重载运算符涉及创建一个函数定义,该函数定义扩展了该运算符可以使用的数据类型的定义。 该函数看起来像常规函数。 它具有返回类型,名称(运算符本身),参数列表,函数主体和返回值。

Overloaded functions are defined as friend functions to the class they are accepting data from. This is so we can pass the needed private member variables of the class directly to the function, even though the overloaded operator function is outside the class definition.

重载函数定义为它们从中接受数据的类的朋友函数。 这样,即使重载的运算符函数在类定义之外,我们也可以将所需的类的私有成员变量直接传递给函数。

Here is what the function definition signature line looks like for overloading the output operator to output Point object member variables:

这是用于重载输出运算符以输出Point对象成员变量的函数定义签名行:

ostream &operator << (ostream &strm, const Point &p)

The function’s return type is ostream, which represents the output stream. The output operator name is next and it is defined as a reference object so that you can chain multiple output operators together. The parameter list consists of an ostream object reference, which is what the Point data is going to be streamed to, and a constant Point object reference so there will be no chance the data is modified in the function. These parameters are also passed by reference for efficiency purposes.

该函数的返回类型为ostream ,它表示输出流。 接下来是输出运算符名称,它被定义为参考对象,以便您可以将多个输出运算符链接在一起。 参数列表由一个ostream对象引用和一个恒定的Point对象引用组成,这是Point数据将要流到的对象,因此不会在函数中修改数据。 这些参数也出于效率目的通过引用传递。

Now let’s look at the function body:

现在让我们看一下函数体:

{
strm << "x:" << x << ", y:" << y;
return strm;
}

The function streams a label for the x and y coordinates along with the member variables themselves to the strm object and this object is returned by the function.

该函数将x和y坐标的标签以及成员变量本身发送到strm对象,该对象由函数返回。

Here is how you declare the function in the class declaration section:

这是在类声明部分中声明函数的方式:

friend ostream &operator << (ostream &, const Point &);

Here is the complete class declaration and definition code, along with a test program:

这是完整的类声明和定义代码,以及测试程序:

class Point {
private:
int x, y;
public:
Point(int, int);
friend ostream &operator << (ostream &, const Point &);
};Point::Point(int newx, int newy) {
x = newx;
y = newy;
}ostream &operator << (ostream &strm, const Point &p) {
strm << "x:" << p.x << ", y:" << p.y;
return strm;
}int main ()
{
Point p1(1,2);
cout << p1 << endl;
return 0;
}

The output from this program is:

该程序的输出为:

x:1, y:2

重载输入运算符 (Overloading the Input Operator)

The code needed to overload the input operator is similar to the code for the output operator, except for obviously using an istream object instead of an ostream object. The overloading function needs to be declared as a friend in the class declaration section and defined outside the class as we did with the overloaded output operator.

重载输入运算符所需的代码与输出运算符的代码相似,除了显然使用istream对象而不是ostream对象。 需要像在重载输出运算符中一样,在类声明部分中将重载函数声明为好友,并在类外部进行定义。

Here is the function declaration and function definition for an overloaded input operator for the Point class:

这是Point类的重载输入运算符的函数声明和函数定义:

friend istream &operator >> (istream &, Point &);istream &operator >> (istream &strm, Point &p) {
cout << "x coordinate: ";
strm >> p.x;
cout << "y coordinate: ";
strm >> p.y;
return strm;
}

Notice that the Point object is a constant parameter because we want the function to modify the member variables of the object. I also provided some prompting information in the function definition that is not strictly necessary but makes the operator more user-friendly.

注意Point对象是一个常量参数,因为我们希望函数修改该对象的成员变量。 我还在功能定义中提供了一些提示信息,这些信息不是严格必要的,但是使操作员更易于使用。

Here is a program that tests both the input operator and the output operator:

这是一个测试输入运算符和输出运算符的程序:

int main ()
{
Point p1;
cout << "Enter a point: " << endl;
cin >> p1;
cout << p1 << endl;
return 0;
}

The output from this program is:

该程序的输出为:

Enter a point:
x coordinate: 5
y coordinate: 8
x:5, y:8

未来有更多超载 (More Overloading Ahead)

These two operators are just the first of many operators we can overload in the service of our class definitions. In my next article I’ll discuss how to overload the assignment operator and the increment and decrement operators.

这两个运算符只是我们可以在我们的类定义的服务中重载的众多运算符中的第一个。 在我的下一篇文章中,我将讨论如何重载赋值运算符以及递增和递减运算符。

Thanks for reading and please email me at mmmcmillan1@att.net with comments and suggestions. If you are interested in my online programming courses, please visit https://learningcpp.teachable.com.

感谢您的阅读,请给我发电子邮件mmmmmillan1@att.net并提供评论和建议。 如果您对我的在线编程课程感兴趣,请访问https://learningcpp.teachable.com

翻译自: https://levelup.gitconnected.com/learning-c-overloading-the-input-and-output-operators-807564b33e62

c 输入输出流运算符重载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值