2011-10-07 10 views
8

나는 기본 클래스가 있고 여러 파생 클래스가 있습니다. 이 파생 된 클래스에 대해 "< <"연산자를 오버로드하고 싶습니다. '+'와 같이 정상적인 연산자의 경우 가상 함수가 트릭을 수행합니다. 표준 컨벤션으로 이해하는 것은 내 클래스 내에 선언문을 작성한 다음 클래스 뒤에 함수를 정의하는 것입니다. 선험적으로 나는 위의 정의에 가상을 추가하는 것이 효과적 일 것이라고 생각할 것이다. 그러나 약간의 생각 (그리고 나의 컴파일러의 에러) 후에 나는 그것이별로 의미가 없다는 것을 깨닫는다.<< 연산자 및 상속 된 클래스

모든 반원이 공개 된 테스트 케이스에서 다른 압정을 시도했습니다. 예를 들어 : - 기본 클래스 연산자 < < 파생 클래스 연산자보다는 호출되는

class Foo{ 
//bla 
}; 

ostream& operator<<(ostream& out, Foo& foo){ 
    cout << "Foo" << endl; 
    return foo; 
} 

class Bar : public Foo{ 
//bla 
}; 

ostream& operator<<(ostream& out, Bar& bar){ 
    cout << "Bar" << endl; 
    return bar; 
} 

/////////////////////// 

Bar bar = Bar(); 
cout << bar << endl; // outputs 'Foo', not 'Bar' 

그래서 어떤 방법이 "나쁜 사라 다형성 (polymorphism)"입니다. 위의 예제에서 파생 클래스에 대해 올바른 연산자가 호출되도록하려면 어떻게해야합니까? 그리고 더 일반적으로, 내 클래스에 개인 멤버가 있다면 보호하고 싶습니다. 친구 키워드를 사용하는 동안 연산자 오버로드를 어떻게 해결할 수 있습니까?

답변

6

가상 도우미 기능을 사용할 수 있습니다. 다음은 완전히 검증되지 않은 예, 그래서 구문의 실수를 용서 :

virtual ostream& Foo::print(ostream& out) const { 
    return out << "Foo"; 
} 

virtual ostream& Bar::print(ostream& out) const { 
    return out << "Bar"; 
} 

// If print is public, this doesn't need to be a friend. 
ostream& operator<<(ostream& out, const Foo& foo) { 
    return foo.print(out); 
} 

편집 : @Omnifarious 제안에 따라 정리은.

+0

완벽하게 작동합니다. 감사. – andyInCambridge

+0

두 가지 결함이 있다고 생각합니다. 하나의 결함은 큰 결함이며 다른 하나는 사소한 결함입니다. 거대한 결점이 첫째로 ... 당신은 절대 눈에 보이지 않게'endl'을 넣어야합니다. 'endl'은 스트림을 플러시 (flush) 시키도록 강요하는데, 이것은 어떤 환경에서는 큰 성능 문제가 될 수 있습니다. ' '\ n' '을 사용하십시오. 사실,'endl'은'\ n '을 출력하는면에서 정의되고, 오버 헤드가 플러시되지 않습니다. 둘째,'return out << "Foo \ n ";". 다소 깨끗함을 느낀다. 개념적으로 전체를 << << 연산의 긴 체인으로 바꾼다 – Omnifarious

+0

@Omnifarious 나는'endl'을'operator <<'오버로드에 두지 않을 것이다. OP의 코드 –

1

operator<<Foo 클래스의 virtual 메서드로 호출을 전달하는 무료 함수입니다.

See it in action.

+0

넵이 작동합니다! 감사. – andyInCambridge

2

일반적으로 단일 무료 친구 기능에 의해 호출되는 기본 클래스에서 다형성 print 메서드를 만듭니다.

+0

인쇄본이 공개이면 친구를 버릴 수 있습니다. –

+0

주위에 좋은 점, 감사합니다. – andyInCambridge

1

올바른 코드 수정을 사용하면 코드 이 제대로 작동합니다. 아무것도을 수행하지 수 :

ostream& operator<<(ostream& out, Foo& foo) { 
    out << "Foo" << endl; // 'out' and not 'cout' 
    return out; // returns 'out' and not 'foo' 
} 

ostream& operator<<(ostream& out, Bar& bar) { 
    out << "Bar" << endl; // 'out' and not 'cout' 
    return out; // returns 'out' and not 'bar' 
} 

Demo합니다. private 회원에 액세스하려면이 기능을 classfriend으로 만들 수 있습니다.

+1

흥미를 자아냅니다. 내 실제 코드에서 나는 cout 대신 올바르게 사용했지만 여전히 작동하지 않았습니다. 필러에 의해 잡히지 않는 미묘한 것이있을 것입니다. // bla 클래스. – andyInCambridge