Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/128.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 操作员是否应<&书信电报;作为朋友或成员函数实现?_C++_Operator Overloading - Fatal编程技术网

C++ 操作员是否应<&书信电报;作为朋友或成员函数实现?

C++ 操作员是否应<&书信电报;作为朋友或成员函数实现?,c++,operator-overloading,C++,Operator Overloading,这基本上就是问题所在,是否有一种“正确”的方法来实现运算符您不能将其作为成员函数来实现,因为隐式这个参数是签名的左侧: bool operator<<(const obj&, const obj&); 然后,由于您不必向ostream添加函数,因此该函数必须是一个自由函数,它是否是朋友取决于它必须访问的内容(如果它不需要访问私有或受保护的成员,则不必使其成为朋友)。它应该作为一个自由的非朋友函数来实现,尤其是像现在的大多数事情一样,输出主要用于诊断和日志记录。为需要

这基本上就是问题所在,是否有一种“正确”的方法来实现
运算符您不能将其作为成员函数来实现,因为隐式
这个
参数是签名的左侧:

bool operator<<(const obj&, const obj&);

然后,由于您不必向
ostream
添加函数,因此该函数必须是一个自由函数,它是否是
朋友取决于它必须访问的内容(如果它不需要访问私有或受保护的成员,则不必使其成为朋友)。

它应该作为一个自由的非朋友函数来实现,尤其是像现在的大多数事情一样,输出主要用于诊断和日志记录。为需要进入输出的所有内容添加常量访问器,然后让输出程序调用这些内容并进行格式化


实际上,我已经开始在一个“ostreamhelpers”头文件和实现文件中收集所有这些ostream输出自由函数,它使次要功能远离类的真正用途。

这里的问题在于您对您所阅读的文章的理解

平等 这篇文章是关于在正确定义布尔关系运算符时遇到问题的人

操作员:

  • 相等==和=
  • 关系<>=
这些运算符在比较相同类型的两个对象时应返回布尔值。通常最容易将这些运算符定义为类的一部分。这是因为类自动成为自己的朋友,因此段落类型的对象可以相互检查(甚至彼此是私有成员)

创建这些独立函数有一个理由,因为这样可以在它们不是同一类型时自动转换两侧,而成员函数只允许自动转换rhs。我发现这是一个纸人的论点,因为你根本不希望自动转换发生在第一位(通常)。但是如果这是你想要的(我不推荐),那么让比较器独立是有利的

流动 流操作员:

  • 操作员>输入
当您使用这些作为流运算符(而不是二进制移位)时,第一个参数是流。由于您无权访问流对象(您无权修改),因此这些对象不能是成员运算符,它们必须位于类的外部。因此,他们必须是该类的朋友,或者可以访问将为您进行流式处理的公共方法

对于这些对象来说,返回对流对象的引用也是一种传统做法,这样您就可以将流操作链接在一起

#include <iostream>

class Paragraph
{
    public:
        explicit Paragraph(std::string const& init)
            :m_para(init)
        {}

        std::string const&  to_str() const
        {
            return m_para;
        }

        bool operator==(Paragraph const& rhs) const
        {
            return m_para == rhs.m_para;
        }
        bool operator!=(Paragraph const& rhs) const
        {
            // Define != operator in terms of the == operator
            return !(this->operator==(rhs));
        }
        bool operator<(Paragraph const& rhs) const
        {
            return  m_para < rhs.m_para;
        }
    private:
        friend std::ostream & operator<<(std::ostream &os, const Paragraph& p);
        std::string     m_para;
};

std::ostream & operator<<(std::ostream &os, const Paragraph& p)
{
    return os << p.to_str();
}


int main()
{
    Paragraph   p("Plop");
    Paragraph   q(p);

    std::cout << p << std::endl << (p == q) << std::endl;
}
#包括
类段落
{
公众:
显式段落(std::string const&init)
:m_para(初始)
{}
std::string const&to_str()const
{
返回m_para;
}
布尔运算符==(段落常量和rhs)常量
{
返回m_para==rhs.m_para;
}
布尔运算符!=(段落常量和rhs)常量
{
//根据==运算符定义!=运算符
返回!(此->运算符==(rhs));
}
bool运算符(如果可能),作为非成员和非友元函数。
正如Herb Sutter和Scott Meyers所描述的,与成员函数相比,更喜欢非友元非成员函数,以帮助提高封装性

在某些情况下,像C++流一样,你没有选择,必须使用非成员函数。

但是,这并不意味着你必须让这些函数成为你的类的朋友:这些函数仍然可以通过你的类访问器访问你的类。如果你成功地以这种方式编写了这些函数,那么你就赢了

关于操作符>原型 我相信你在问题中给出的例子是错误的

ostream & operator<<(ostream &os) {
    return os << paragraph;
}
ostream和运算符函数原型
第一种是作为功能:

// T << Paragraph
T & operator << (T & p_oOutputStream, const Paragraph & p_oParagraph)
{
   // do the insertion of p_oParagraph
   return p_oOutputStream ;
}

// T >> Paragraph
T & operator >> (T & p_oInputStream, const Paragraph & p_oParagraph)
{
   // do the extraction of p_oParagraph
   return p_oInputStream ;
}
//T段
T&operator>>(T&p_输入流、常量段落和p_阴影图)
{
//进行p_图像的提取
返回p_到输出流;
}
通用运算符>方法原型 第二种方法是:

// T << Paragraph
T & T::operator << (const Paragraph & p_oParagraph)
{
   // do the insertion of p_oParagraph
   return *this ;
}

// T >> Paragraph
T & T::operator >> (const Paragraph & p_oParagraph)
{
   // do the extraction of p_oParagraph
   return *this ;
}
//T段
T&T::运算符>>(常量段落和p_oparragraph)
{
//进行p_图像的提取
归还*这个;
}
注意,要使用这种表示法,您必须扩展T的类声明。对于STL对象,这是不可能的(您不应该修改它们…)

如果T是C++流怎么办?

这里是C++流相同的>运算符的原型。

对于通用基本流和基本流

注意,是流的情况,因为你不能修改C++流,你必须实现函数。

friend bool operator<<(obj const& lhs, obj const& rhs);
// OUTPUT << Paragraph
template <typename charT, typename traits>
std::basic_ostream<charT,traits> & operator << (std::basic_ostream<charT,traits> & p_oOutputStream, const Paragraph & p_oParagraph)
{
   // do the insertion of p_oParagraph
   return p_oOutputStream ;
}

// INPUT >> Paragraph
template <typename charT, typename traits>
std::basic_istream<charT,traits> & operator >> (std::basic_istream<charT,traits> & p_oInputStream, const CMyObject & p_oParagraph)
{
   // do the extract of p_oParagraph
   return p_oInputStream ;
}
//输出段落
模板
std::basic_istream&operator>>(std::basic_istream&p_Outstream,常量CMyObject&p_Oparragraph)
{
//进行p_opargraph的提取
返回p_到输出流;
}
对于char istream和ostream 以下代码仅适用于基于字符的流

// OUTPUT << A
std::ostream & operator << (std::ostream & p_oOutputStream, const Paragraph & p_oParagraph)
{
   // do the insertion of p_oParagraph
   return p_oOutputStream ;
}

// INPUT >> A
std::istream & operator >> (std::istream & p_oInputStream, const Paragraph & p_oParagraph)
{
   // do the extract of p_oParagraph
   return p_oInputStream ;
}
//输出A
std::istream&operator>>(std::istream&p_oInputStream,常量段落&p_oparragraph)
{
//进行p_opargraph的提取
返回p_到输出流;
}
Rhys Ulerich评论说基于字符的代码只是一种“专门化”当然,Rhys是对的:我不建议使用基于字符的示例。之所以在这里给出这个示例,是因为它更易于阅读。因为它只适用于基于字符的流,所以在wchar_________________________________________


希望这会有所帮助。

operatorfriend operator=与类具有同等权利

friend std::ostream& operator<<(std::ostream& os, const Object& object) {
    os << object._atribute1 << " " << object._atribute2 << " " << atribute._atribute3 << std::endl;
    return os;
}

friend std::ostream&operator为了完成,我想补充一点,您确实可以创建一个operator
ostream&operator顺便说一句,您应该
// T << Paragraph
T & operator << (T & p_oOutputStream, const Paragraph & p_oParagraph)
{
   // do the insertion of p_oParagraph
   return p_oOutputStream ;
}

// T >> Paragraph
T & operator >> (T & p_oInputStream, const Paragraph & p_oParagraph)
{
   // do the extraction of p_oParagraph
   return p_oInputStream ;
}
// T << Paragraph
T & T::operator << (const Paragraph & p_oParagraph)
{
   // do the insertion of p_oParagraph
   return *this ;
}

// T >> Paragraph
T & T::operator >> (const Paragraph & p_oParagraph)
{
   // do the extraction of p_oParagraph
   return *this ;
}
// OUTPUT << Paragraph
template <typename charT, typename traits>
std::basic_ostream<charT,traits> & operator << (std::basic_ostream<charT,traits> & p_oOutputStream, const Paragraph & p_oParagraph)
{
   // do the insertion of p_oParagraph
   return p_oOutputStream ;
}

// INPUT >> Paragraph
template <typename charT, typename traits>
std::basic_istream<charT,traits> & operator >> (std::basic_istream<charT,traits> & p_oInputStream, const CMyObject & p_oParagraph)
{
   // do the extract of p_oParagraph
   return p_oInputStream ;
}
// OUTPUT << A
std::ostream & operator << (std::ostream & p_oOutputStream, const Paragraph & p_oParagraph)
{
   // do the insertion of p_oParagraph
   return p_oOutputStream ;
}

// INPUT >> A
std::istream & operator >> (std::istream & p_oInputStream, const Paragraph & p_oParagraph)
{
   // do the extract of p_oParagraph
   return p_oInputStream ;
}
#include <iostream>
#include <string>
using namespace std;

class Samp
{
public:
    int ID;
    string strName; 
    friend std::ostream& operator<<(std::ostream &os, const Samp& obj);
};
 std::ostream& operator<<(std::ostream &os, const Samp& obj)
    {
        os << obj.ID<< “ ” << obj.strName;
        return os;
    }

int main()
{
   Samp obj, obj1;
    obj.ID = 100;
    obj.strName = "Hello";
    obj1=obj;
    cout << obj <<endl<< obj1;

} 
friend std::ostream& operator<<(std::ostream& os, const Object& object) {
    os << object._atribute1 << " " << object._atribute2 << " " << atribute._atribute3 << std::endl;
    return os;
}
#include <iostream>
#include <string>

using namespace std;

struct Widget
{
    string name;

    Widget(string _name) : name(_name) {}

    ostream& operator << (ostream& os)
    {
        return os << name;
    }
};

int main()
{
    Widget w1("w1");
    Widget w2("w2");

    // These two won't work
    {
        // Error: operand types are std::ostream << std::ostream
        // cout << w1.operator<<(cout) << '\n';

        // Error: operand types are std::ostream << Widget
        // cout << w1 << '\n';
    }

    // However these two work
    {
        w1 << cout << '\n';

        // Call to w1.operator<<(cout) returns a reference to ostream&
        w2 << w1.operator<<(cout) << '\n';
    }

    return 0;
}