그것이 기본적으로 질문입니다. “올바른”구현 방법이 operator<<
있습니까? 이것을 읽으면 다음과 같은 것을 볼 수 있습니다.
friend bool operator<<(obj const& lhs, obj const& rhs);
같은 것보다 선호됩니다
ostream& operator<<(obj const& rhs);
하지만 왜 둘 중 하나를 사용해야하는지 잘 모르겠습니다.
내 개인 사례는 다음과 같습니다.
friend ostream & operator<<(ostream &os, const Paragraph& p) {
return os << p.to_str();
}
그러나 나는 아마도 할 수 있습니다.
ostream & operator<<(ostream &os) {
return os << paragraph;
}
이 결정의 근거는 무엇입니까?
참고 :
Paragraph::to_str = (return paragraph)
여기서 단락은 문자열입니다.
답변
여기서 문제는 링크 하는 기사에 대한 해석에 있습니다 .
평등
이 문서는 bool 관계 연산자를 올바르게 정의하는 데 문제가있는 사람에 대한 것입니다.
운영자 :
- 같음 == 및! =
- 관계 <> <=> =
이러한 연산자는 동일한 유형의 두 개체를 비교할 때 부울을 반환해야합니다. 일반적으로 이러한 연산자를 클래스의 일부로 정의하는 것이 가장 쉽습니다. 이는 클래스가 자동으로 자신의 친구가되므로 Paragraph 유형의 개체가 서로를 검사 할 수 있기 때문입니다 (서로 개인 멤버도 포함).
이러한 독립 함수를 만들기위한 인수가 있습니다. 이렇게하면 자동 변환이 동일한 유형이 아닌 경우 양쪽을 모두 변환 할 수 있고 멤버 함수는 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;
}
답변
암시 적 this
매개 변수가 <<
-operator 의 왼쪽 이기 때문에 멤버 함수로 수행 할 수 없습니다 . (따라서 ostream
-class에 멤버 함수로 추가해야합니다 . 좋지 않습니다. 🙂
없이 무료 기능으로 할 수 있습니까? friend
있습니까? 이것이 제가 선호하는 것입니다. 이것이 ostream
클래스의 핵심 기능이 아니라 와의 통합임을 분명히하기 때문 입니다.
답변
가능하다면 비회원 및 친구가 아닌 기능으로 활동합니다.
Herb Sutter와 Scott Meyers가 설명했듯이 캡슐화를 늘리기 위해 멤버 함수보다 친구가 아닌 비 멤버 함수를 선호합니다.
C ++ 스트림과 같은 일부 경우에는 선택권이 없으며 비 멤버 함수를 사용해야합니다.
그러나 그렇다고해서 이러한 함수를 클래스의 친구로 만들어야한다는 의미는 아닙니다. 이러한 함수는 클래스 접근자를 통해 클래스에 액세스 할 수 있습니다. 이런 식으로 이러한 함수를 작성하는 데 성공하면 이겼습니다.
운영자 << 및 >> 프로토 타입 정보
귀하의 질문에 제시 한 예가 잘못되었다고 생각합니다. 예를 들면 다음과 같습니다.
ostream & operator<<(ostream &os) {
return os << paragraph;
}
이 방법이 스트림에서 어떻게 작동 할 수 있는지 생각조차 할 수 없습니다.
다음은 << 및 >> 연산자를 구현하는 두 가지 방법입니다.
T 유형의 스트림과 유사한 객체를 사용한다고 가정 해 보겠습니다.
그리고 Paragraph 유형의 객체 관련 데이터를 T에서 추출 / 삽입하려고합니다.
일반 연산자 << 및 >> 함수 프로토 타입
첫 번째 기능은 다음과 같습니다.
// 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 ;
}
이 표기법을 사용하려면 T의 클래스 선언을 확장해야합니다. STL 객체의 경우 이것은 불가능합니다 (수정해서는 안됩니다 …).
T가 C ++ 스트림이면 어떻게 될까요?
다음은 C ++ 스트림에 대한 동일한 << 및 >> 연산자의 프로토 타입입니다.
일반 basic_istream 및 basic_ostream의 경우
스트림의 경우 C ++ 스트림을 수정할 수 없으므로 함수를 구현해야합니다. 이는 다음과 같은 의미입니다.
// 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 ;
}
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 ;
}
Rhys Ulerich는 문자 기반 코드가 그 위에있는 일반 코드의 “특수화”에 불과하다는 사실에 대해 언급했습니다. 물론 Rhys가 맞습니다. 문자 기반 예제를 사용하는 것은 권장하지 않습니다. 읽기가 더 간단하기 때문에 여기에만 제공됩니다. char 기반 스트림으로 만 작업하는 경우에만 실행 가능하므로 wchar_t 코드가 일반적인 플랫폼 (예 : Windows)에서는 피해야합니다.
이것이 도움이되기를 바랍니다.
답변
특히 요즘 대부분의 경우와 같이 출력이 주로 진단 및 로깅에 사용되는 경우 친구가 아닌 무료 기능으로 구현해야합니다. 출력에 필요한 모든 것에 대한 const 접근자를 추가 한 다음 출력자가 해당 접근자를 호출하고 형식을 지정하도록합니다.
실제로 “ostreamhelpers”헤더 및 구현 파일에서 이러한 모든 ostream 출력 무료 함수를 수집했습니다.이 기능은 클래스의 실제 목적과는 거리가 먼 보조 기능을 유지합니다.
답변
서명 :
bool operator<<(const obj&, const obj&);
이것은 오히려 의심 맞지 않는 것 같다 stream
가 연산자 오버로딩 학대의 경우처럼 보이는 있도록 규칙이나 비트 규칙을 operator <
반환해야 bool
하지만,operator <<
해야 아마도 다른 것을 반환해야합니다.
그렇게 의미했다면 다음과 같이 말하십시오.
ostream& operator<<(ostream&, const obj&);
그런 다음 ostream
필요에 따라 함수를 추가 할 수 없기 때문에 함수는 액세스해야하는 항목에 따라 자유 함수 여야합니다 friend
(비공개 멤버 또는 보호 된 멤버에 액세스 할 필요가없는 경우 만들 필요가 없습니다). 친구).
답변
완료를 위해 실제로 연산자를 만들 수 있음을 추가하고 싶습니다.ostream& operator << (ostream& 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;
}
그래서 요약하자면-할 수는 있지만 그렇게해서는 안됩니다. 🙂
답변
친구 연산자 = 클래스와 동등한 권리
friend std::ostream& operator<<(std::ostream& os, const Object& object) {
os << object._atribute1 << " " << object._atribute2 << " " << atribute._atribute3 << std::endl;
return os;
}