2016-06-25 3 views
1

방법이 있습니까, 개인 함수를 통해 인터페이스를 구현하는 파생 클래스를 강제로 있습니다. 내가 원하는 것은 다음과 같다.강제로 파생 클래스를 개인 메서드를 구현하려면

class base{ 
private: 
    virtual void do_something() = 0; // This can be private/public/protected 
}; 

파생 된 클래스 공개하지 않은 do_something()의 구현을 제공해야한다. 당신이 짐작할 수 있듯이, 여기 내 목적은 사용자가 함수의 구현을 제공하도록하지만 기본 클래스가 호출 할 것이고 class derived : public base{...}의 객체는 do_something()을 호출 할 수 없다는 것을 확인하는 것이다. 개인적인?

편집 : 그냥 추가하고 싶다면 class derived : base은 (는) 사용자가 아니고 (내가) 작성한 것이 아닙니다. 사용 사례는 do_something()이 호출 될 때 기본 클래스의 함수가 제어되는지 확인하는 것입니다.

+2

실제 사용 사례는 무엇입니까? –

+0

@ πάντεῥεῖ 템플릿 메서드 패턴? – juanchopanza

+0

'derived '가 내부적으로'do_something()'을 호출하지 못하게한다는 것을 의미합니까? – juanchopanza

답변

0

do_something을 클래스 멤버로 선언하는 대신 constructor 호출에서 함수 객체를 전달하기 위해 파생 클래스가 필요할 수 있습니다. 하지만 이것은 추한 것입니다. 차라리 "파생 된 전화를 걸 수 없음"에 대한 요구 사항을 삭제하고 protected을 사용합니다.

#include <functional> 
#include <iostream> 

class base { 
public: 
    base(std::function<void()> do_something) : _do_something(do_something) {} 
    void act() { 
    _do_something(); 
    } 

private: 
    std::function<void()> _do_something; 
}; 

class derived : public base { 
public: 
    derived() : base([&]{std::cout << "impl: " << prop1 << ", " << prop2 << std::endl;}) {} 

private: 
    int prop1; 
    int prop2; 
}; 

int main(int argc, char* argv[]) { 
    derived d; 
    d.act(); 
    return 0; 
} 
2

TL; DR : 아니오 .


class base { 
private: 
    virtual void do_something() = 0; 
}; 

을 감안할 때 당신은 비공개로 do_something을 구현하는 파생 클래스를 강제 할 수 없다. 다음은 법적 : 당신이 개인으로 강제 할 수

struct derived : base { 
    void do_something() { ... } // public 
}; 

하더라도, 클래스는 항상 자신의 개인 메서드를 호출 할 수 있습니다. "class derived : public base{...}의 객체는 do_something()으로 호출 할 수 없습니다."라는 요구 사항에 반하는 것입니다.


그리고 심지어 당신이 그것을 호출 할 수없이하는 방법을 구현하는 파생 클래스를 강제 수 있다면

, 그들은 여전히 ​​이런 식으로 해결 수 :
struct derived2 : base { 
    void do_something_impl() { .... } 
private: 
    void do_something() { do_something_impl(); } 
}; 

지금 그들은 단지 직접 do_something_impl()를 호출 할 수 있습니다.

+0

그래, 첫 번째 경우는 나를 혼란스럽게 만든다. 기본 클래스에서 개인 가상으로 함수를 선언하더라도 파생 클래스의 공용 함수가이를 재정의 할 수 있습니다. 나는 이것이 가능하지 않다고 생각했을 것이다. 그러나 분명히 코드가 컴파일된다. 따라서 합법적 인 C++이어야합니다. – cplusplusrat

0

당신은 그렇게 할 수 없습니다.
@melpomene 님의 멋진 답변보기.


문제가 파생 클래스에 대한 참조를 가지고 하나에 공개적으로 액세스 할 것이라고 경우이 작업을 수행 할 수 있습니다 상속 당신도 을 시뮬레이션 할 수있는 특정 한계 내에서

class base { 
private: 
    virtual void do_something() = 0; 
}; 

template<typename T> 
class intermediate: public base, private T { 
    void do_something() override { 
     T::do_something(); 
    } 
}; 

class derived { 
public: 
    void do_something() { } 
}; 

int main() { 
    auto *d = new intermediate<derived>{}; 
    base *b = d; 
    // not allowed, it's private 
    // d->do_somerhing(); 
    // b->do_something(); 
} 

을 데이터 멤버 (물론, 나는 알고있다, 그들은 전혀 상속되지 않지만, 친구 여기에 도움이 될 수 있습니다) :

template<typename T> 
class intermediate: public base, private T { 
    friend T; 

    void do_something() override { 
     T::do_something(*this); 
    } 

private: 
    int foo; 
}; 

class derived { 
public: 
    void do_something(intermediate<derived> &ref) { 
    ref.foo = 42; 
    } 
}; 
0

파생 클래스가 기본 클래스의 멤버 인 private에 액세스 할 수 없습니다. 파생 클래스는 다음 do_something()를 오버라이드 (override) 할 필요가 있다면`대신 보호되어야한다 : private해야

class base 
{ 
protected: 
    virtual void do_something() = 0; 
}; 

do_something() 경우에 당신이 do_something() 통화 및 파생 클래스보다 우선 protected 방법을 선언해야합니다. 특히 do_something()이 파생 클래스가 재정의해서는 안되는 다른 작업을 수행해야하는 경우 특히 그렇습니다.

class base 
{ 
private: 
    void do_something() 
    { 
     //... 
     actually_do_something(); 
     //... 
    } 

protected: 
    virtual void actually_do_something() = 0; 
}; 
관련 문제