2016-11-16 4 views
6
#include <iostream> 

struct A 
{ 
    virtual void foo(){ std::cout << "A"; }; 
}; 

struct B : public A 
{ 
private: 
    void foo() override { std::cout << "B"; } 
}; 

int main() 
{ 
    A *p = new B; 
    p->foo();  // prints B 

// B b; 
// b.foo();  // error: foo is private 
    return 0; 
} 

// g++ -std=c++11 -Wall -Wextra -Wpedantic main.cpp && ./a.out 

따라서 우리는 B.foo()을 다형 적으로 호출 할 수 있지만 직접적으로 호출 할 수는 없습니다. 누군가이 기능을 사용하고자 할 때 유스 케이스가 있습니까?개인 공개 가상 메서드의 사용 사례가 있습니까?

답변

2

메소드를 다형 적으로 호출하지 않게됩니다. 즉, 범위 분석 연산자를 사용하여 메소드에 직접 액세스하면 코드를 유지하기가 어려울 수 있습니다. 모두가 경험 많은 개발자 (대규모 코드베이스에 아마도 기여한 과학 프로그래머)가 아니라는 것을 알고있는 환경에서 코드를 보호하는 패턴을 도입하는 것이 가치가 있습니다!

즉, 자바는 나쁜 스타일이라고 생각할 때이를 명시 적으로 금지합니다.

+1

다시 말해서 Java가 금지하지 않는 것은 무엇입니까? –

5

일종의 기본 클래스의 디자인에 따라 다릅니다. 당신이 기본 클래스를

class Stream { 
public: 
    virtual bool canSeek() = 0; 
    virtual void seek(int offset) = 0; 
}; 

참고가 있다고 가정 :이 예는 기본 클래스 라이브러리 Stream 클래스는 정말 같은 가상 CanSeek 속성을 가지고 닷넷 세계에서 온다. 나는 이것이 양측의 유효한 논증을 볼 수있는 좋은 디자인인지 여부에 관해 논의하기를 원하지 않는다. 그러한 기본 클래스가 실제로 존재하기 만하면 충분합니다.

자, 파생 클래스는 기술적으로 필요하기 때문에이 파생 클래스에서

class SpecificStream final : Stream { 
private: 
    virtual bool canSeek() { return false; } 
    virtual void seek(int offset) { throw "no seek for you"; } 
} 

seek 모두에서 구현된다는 사실이 있음을 지정할 수 있습니다. 그러나이 코드를 다루는 코드는 이미 seek 함수가이 클래스에서 전혀 쓸모 없으며 호출되어서는 안됨을 이미 알고 있습니다. 베이스 Stream 클래스를 기준으로 코딩 할 때는 canSeek()의 결과를 확인하고 결과가 true 인 경우에만 seek으로 전화하는 것이 좋습니다. SpecificStream 클래스를 대상으로 코딩 할 때 canSeek()을 확인하는 것은 의미가 없으며 그 결과는 정적으로 알려져 있으므로 seek()으로 전화하는 것은 의미가 없습니다. 이러한 호출이 프로그래머 오류 일 경우 컴파일러가 이러한 호출에 유용한 메시지를 제공하는 데 도움이됩니다.