2014-11-18 3 views
3

코드를 살펴보십시오.기본 클래스에 대한 참조를 사용하여 파생 클래스의 private 멤버 함수에 액세스

class Abstract_base { 
    public: 
     virtual ~Abstract_base() {} 

     virtual void f1() = 0; 
     virtual void f2() = 0; 
}; 

기본 클래스는 다음과 같습니다 :

class Base : public Abstract_base { 
    public: 
     virtual ~Base() {} 

     virtual void f1() override { cout << "f1" << endl; } 
     virtual void f2() override { cout << "f2" << endl; } 
}; 

나는 다음과 같이 두 개의 파생 클래스가 있습니다

class Derived_1 : public Base { 
    public: 
     virtual ~Derived_1() {} 

    private: 
     virtual void f2() override { cout << "Derived_1::f2()" << endl; } 

}; 

class Derived_2 : public Base { 
    public: 
     virtual ~Derived_2() {} 

    private: 
     virtual void f1() override { cout << "Derived_2::f1()" << endl; } 
}; 

을 마지막으로 내가 처리기가 I는 다음과 같다 인터페이스를 다음과 같은 클래스 :

class Handler { 
    public: 
     Handler (Abstract_base& b) : base (b) {} 
     virtual ~Handler() {} 

     void process_1() { 
      base.f1(); 
     } 

     void process_2() { 
      base.f2(); 
     } 

    private: 
     Abstract_base& base; 
}; 

그리고 MAIN.CPP은 다음과 같습니다 der1.f2()와 der2.f1()가 개인이기 때문에

int main (int argc, char** argv) { 

    Derived_1 der1; 
    der1.f2(); 

    Derived_2 der2; 
    der2.f1(); 

    Handler handler1 (der1); 
    handler1.process_2(); 

    Handler handler2 (der2); 
    handler2.process_1(); 

    return 0; 
} 

물론 코드는 컴파일되지 않습니다,하지만 난이 두 가지 지시 사항을 주석 경우와 handler1을 둡니다. process_2()와 handler2.process_1() 명령, 코드를 컴파일하고 생성합니다 출력 :

Derived_1::f2() 
Derived_2::f1() 

질문 :

가 어떻게 토륨 참조를 사용하여이 두 개인 멤버 함수를 호출 방지 할 수 있습니다 Abstract_base 클래스? 사용자가 Derived_1의 f2() 및 Derived_2의 f1()에 액세스 할 수 없도록하려는 것입니다.

필자가 아는 한 Derived_1 :: f2() 및 Derived_2 :: f1()에 delete 키워드를 사용할 수 없습니다.

이 문제에 대한 해결책을 제안 해 주시겠습니까?

솔루션

나는 해결책 중 하나가 처리기이 같은 템플릿 클래스를 만들 수 있다는 것을 알고

template <class B> 
class Handler_templ { 
    public: 
     Handler_templ (B& b) : base (b) { } 
     virtual ~Handler_templ() {} 

     void process_1() { 
      base.f1(); 
     } 

     void process_2() { 
      base.f2(); 
     } 

    private: 
     B& base; 
}; 

과 같이 사용 :

Handler_templ<Derived_1> h1 (der1); 
Handler_templ<Derived_2> h2 (der2); 

h1.process_2(); 
h2.process_1(); 

놀라운 무엇 왜 Handler 클래스를 사용하여 이러한 private 멤버 함수를 호출 할 수 있습니까? 어떤 제안이라도 매우 감사 할 것입니다. 감사합니다

, 아르투르

+2

'Handler' 클래스를 사용하면'Abstract_base'에 대한 참조를 통해 메소드에 액세스합니다.이 참조는 함수의 액세스를 결정하는 데 사용됩니다 (여기서는'public'). 따라서 코드가 컴파일됩니다. – Niall

답변

1

_ "나는 Abstract_base 클래스에 대한 참조를 사용하여이 두 개인 멤버 함수를 호출 방지 할 수 있습니까? 난 그냥 사용자가 Derived_1f2()에 액세스하지 않고 f1()의 'Derived_2'._

파생 클래스 선언을 통해 범위 연산자를 사용하여 이러한 함수를 숨길 방법이 없습니다.

"내가이 개인 멤버 함수를 호출 할 수있는 핸들러 클래스를 사용하는 이유는 무엇입니까?"귀하의 샘플

class Base : public Abstract_base { 
public: 
    virtual ~Base() {} 
    virtual void f1() override { cout << "f1" << endl; } 
    virtual void f2() override { cout << "f2" << endl; } 
}; 

class Derived_1 : public Base { 
public: 
    virtual ~Derived_1() {} 
private: 
    virtual void f2() override { cout << "Derived_1::f2()" << endl; } 
}; 

class Derived_2 : public Base { 
public: 
    virtual ~Derived_2() {} 
private: 
    virtual void f1() override { cout << "Derived_2::f1()" << endl; } 
}; 

는 파생 클래스에서 private 기능을 사용하여 public 기본 클래스 함수를 재정의 할 수 있도록 완벽하게 괜찮아요에 관해서는

.
이 함수를 오버라이드 (override) Base/Abstract_base 클래스 인터페이스를 통해 계속 볼 수 있습니다.

범위 지정자는 클라이언트를 직접 호출하기 위해 액세스 할 수 없게 만듭니다.

1

Abstract_base 클래스에 대한 참조를 사용하여이 두 가지 전용 멤버 함수를 호출하는 것을 방지 할 수 없습니다. 기본 클래스의 참조 또는 포인터로 메서드에 액세스하면 파생 클래스의 액세스 권한이 고려되지 않습니다. (어떻게 컴파일러는 것을 알 수 있습니까?)

를리스 코프 치환 원칙 (LSP)에 따르면, 그것을 모른 채 파생 클래스의 객체를 사용할 수 있어야합니다 기본 클래스에 대한 포인터 나 참조를 사용

기능 .

+0

_ "할 수 없어요."_ 실제로는 할 수 없습니까? 클래스의 'private'범위에서 구현되는 가상 함수를 호출하는 클라이언트를 방지 하시겠습니까? –

+1

나는 OP의 질문에 따라 그것을 고쳤습니다. – songyuanyao

0

당신은 그렇게 할 수 없습니다.

Derived_1 der1; 
((Abstract_base*)&der1)->f2(); // 1 

그리고 포인터 또는 참조 변환 :

Derived_1 d; 

Abstract_base* bp = &d; // 2 
Abstract_base& ref = d; // 2 

C++가 기본 포인터/참조로 변환 을 중지하는 조항이없는, 또는 개체 슬라이싱을 수행하기 위해 두 가지를 막을 수 없다 기지에. C++에서는 파생 클래스가 지정된 보호 수준에서 가상 함수를 구현해야한다고 명령하지 않습니다.