C++ class iostream overloading

C++ class iostream overloading

本文关键字:overloading iostream class C++      更新时间:2023-10-16

我还处于C++的基本学习过程中,在进行运算符重载部分时,我无法理解iostream重载运算符的函数调用步骤。

我感到困惑的是,当"重载iostream函数是通过friend命令在我的类定义之外定义的"时,下面的C++代码可以区分基本类型数据iostream调用和类iostream呼叫请看下面的例子。

#ifndef PHONENUMBER_H
#define PHONENUMBER_H
#include <iostream>
#include <string>
class PhoneNumber
{
    friend std::ostream &operator<<( std::ostream &, const PhoneNumber & )
    friend std::istream &operator>>( std::istream &, PhoneNumber & )
private:
    std::string areaCode;
    std::string exchange;
    std::string line;
};
#endif

现在是重载函数的定义。

#include <iomanip>
#include "PhoneNumber.h"
using namespace std;
ostream &operator<<( ostrea &output, const PhoneNumber &number )
{
    output << "(" number.areaCode << ")" << number.exchange << "-" << number.line;
    return output;
}
istream &operator>>( istream &input, PhoneNumber &number )
{
    input.ignore();
    input >> setw( 3 ) >> number.areaCode;
    input.ignore( 2 );
    input >> setw( 3 ) >> number.exchange;
    input.ignore();
    input >> setw( 4 ) >> number.line;
    return input;
}

现在是主要功能。

#include <iostream>
#include "PhoneNumber.h"
using namespace std;
int main()
{
    PhoneNumber phone;
    cout << "Enter phone number in the form (123) 456-7890" << endl;
    cin >> phone;
    cout << "The phone number entered was: ";
    cout << phone << endl;
}

根据我的理解,通常函数调用(甚至是运算符重载函数)都必须遵循声明格式。因此,调用重载<lt;(或>>)运算符函数,则用户必须编写如下行:"ostream a;"然后是"cin>>(a,电话);"。同样在上面的例子中,它看起来像是"cin>>电话;"会被通知并直接指向好友功能。根据我的理解,为了遵循这些步骤,接线员呼叫"cin>>电话"将首先查看PhoneNumber.h声明。但是,运算符声明不在PhoneNumber.h中。它只是作为朋友"被提及"。(我对"friend"命令的理解是,类将简单地授予非成员函数(或类)访问其私有数据或成员函数的权限。)因此,调用应该混淆编译器调用上面代码中的显式运算符函数或iostream中的隐式运算符函数。

我想我的问题是:1。操作员如何"<lt;'和">>"调用的格式与它们的声明方式不同?2.当运算符调用未在.h文件中"声明"时,如何识别它?C++如何知道跳过.h并直接跳转到用户定义的运算符函数中?

您的问题中有一些明显的误解,但其余的我无法真正解析。希望以下内容足以解决您的查询。

此:

cin >> x;

这是语法糖(更像你想象的函数调用语法):

cin.operator>>(x);

或者有时(在这种情况下)这样:

operator>>(cin, x);

你不能随便为这两种情况编造一个额外的论据!

  1. 因为它们被声明为"运算符"-函数。与你在问题中所写的相反,这不是一个"正常"的函数。一个正常的函数声明应该是:std::ostream &<<(std::ostream &, const Phonenumber &)(我认为它不会编译)。但是您将它声明为std::ostrean &operator<<(std::ostream &, const Phonenumber &),这使它成为一个运算符重载。

  2. 这看起来确实很棘手,但这是因为编译器中有一个编译步骤和链接步骤。在编译时,编译器会将友元函数声明解析为您在另一个文件中编写的流运算符函数。它们匹配,因为函数声明是相同的,并且它们被声明为友元函数。在链接时(这是构建最终程序的地方),如果您告诉链接器组合所有这些文件,链接器将尝试为主循环中使用的函数找到匹配项。如果没有找到它们,您将得到类似于:Undefined reference to ...的内容

    由于运算符调用是在头文件中声明的(你说它们不是,但它们是-它们只是声明为友元函数),编译器和链接器都会成功。编译器不会告诉你:Use of undeclared function ...,链接器也不会告诉你,Undefined reference to...