보호 된 생성자의 실제 용도는 무엇입니까?
왜 아무도 생성자를 보호한다고 선언합니까? 생성자는 스택에서 생성을 허용하지 않기 위해 비공개로 선언된다는 것을 알고 있습니다.
클래스가 추상 클래스 인 경우 보호 된 생성자가 정확히 맞습니다. 이 상황에서는 객체가 클래스에서 인스턴스화되는 것을 원하지 않고 상속에만 사용합니다.
특정 구성 매개 변수 집합을 파생 클래스로 제한해야하는 경우와 같은 다른 사용 사례가 있습니다.
한 가지 용도는 공장 패턴 일 수 있습니다.
비공개 생성자는 생성자에 의해서만 보장 될 수없는 생성 요구 사항이있을 때 유용합니다. 예를 들어, 생성자 바로 뒤에 초기화 메서드를 호출해야하거나 객체가 컨테이너 / 관리자 객체에 자신을 등록해야하는 경우 생성자 외부에서 수행해야합니다. 생성자에 대한 액세스를 제한하고 팩토리 메서드 만 제공하면 사용자가받는 모든 인스턴스가 모든 보장을 이행하도록 할 수 있습니다. 이것은 또한 일반적으로 Singleton을 구현하는 데 사용되며, 이는 클래스가 만드는 또 다른 보증 일뿐입니다 (단일 인스턴스 만 있음).
생성자를 private이 아닌 보호로 만드는 이유는 private 대신에 다른 메서드 나 필드를 보호하도록 만드는 것과 동일하므로 자식이 상속 할 수 있습니다. 파생 클래스의 인스턴스에 대한 참조를 반환하는 기본 클래스에 가상이 아닌 공용 팩토리 메서드가 필요할 수 있습니다. 파생 클래스는 분명히 부모 생성자에 대한 액세스를 원하지만 여전히 팩토리 외부에서 생성하고 싶지는 않습니다.
보호 된 생성자는 메서드가 순수 가상이 아닌 경우 클래스를 효과적으로 추상화하는 데 사용할 수 있습니다.
친구 클래스가 재정의하지 않고 계속 사용할 수 있기 때문에 C ++의 의미에서 추상적이지는 않지만이를 선언해야합니다.
보호 된 생성자는 파생 된 멤버 만 해당 생성자를 사용하여 클래스 (및 파생 된 인스턴스)의 인스턴스를 생성 할 수 있음을 의미합니다. 이것은 약간 닭과 계란처럼 들리지만 때로는 클래스 팩토리를 구현할 때 유용합니다.
부작용이있는 팩토리 방법.
class mine {
private:
mine () {};
protected:
mine(int id) : m_id(id) {};
int m_id;
static int m_count;
public:
static mine* CreateOneOfMe() {
return mine(m_count++);
}
int GetId() { return m_id; }
};
이것은 클래스의 인스턴스를 생성하고 각각이 고유 한 증분 정수 ID를 갖도록 보장합니다. 사용하려는 생성자가 기본값이 아닌 경우 기본값도 숨겨야합니다.
하위 클래스가 인스턴스화자가 직접 액세스 할 수없는 생성자를 사용하도록합니다.
이를 생성 할 수있는 클래스를 제한하는 데 사용할 수 있습니다. 예를 들면 다음과 같습니다.
class Level
{
private:
Level();
¨Level();
friend class LevelManager;
};
인스턴스를 생성 할 수있는 유일한 클래스는 LevelManager 클래스이므로 Level 인스턴스가 LevelManager에 생성되었음을 항상 알 수 있습니다.
보호 된 생성자의 한 가지 용도는 CRTP 패턴을 구현하는 것입니다. 아래 코드를 참조하세요.
#include <iostream>
#include <assert.h>
template <class T>
class ComparableMixin {
public:
bool operator !=(ComparableMixin &other) {
return ~(*static_cast<T*>(this) == static_cast<T&>(other));
}
bool operator <(ComparableMixin &other) {
return ((*(this) != other) && (*static_cast<T*>(this) <= static_cast<T&>(other)));
}
bool operator >(ComparableMixin &other) {
return ~(*static_cast<T*>(this) <= static_cast<T&>(other));
}
bool operator >=(ComparableMixin &other) {
return ((*static_cast<T*>(this) == static_cast<T&>(other)) || (*(this) > other));
}
protected:
ComparableMixin() {}
};
class Integer: public ComparableMixin<Integer> {
public:
Integer(int i) {
this->i = i;
}
int i;
bool operator <=(Integer &other) {
return (this->i <= other.i);
}
bool operator ==(Integer &other) {
return (this->i == other.i);
}
};
int main() {
Integer i(0) ;
Integer j(1) ;
//ComparableMixin<Integer> c; //compilation error!
assert (i < j );
assert (i != j);
assert (j > i);
assert (j >= i);
return 0;
}
참고 URL : https://stackoverflow.com/questions/1057221/what-are-practical-uses-of-a-protected-constructor
'your programing' 카테고리의 다른 글
게시하는 링크에 Rails link_to 사용 (0) | 2020.10.14 |
---|---|
JavaScript의 인라인 이벤트 처리기에 이벤트를 인수로 전달하는 방법은 무엇입니까? (0) | 2020.10.14 |
Asp.Net MVC의 DataAnnotations StringLength에있는 텍스트 상자의 maxlength 특성 (0) | 2020.10.14 |
선택적 매개 변수의 기본값으로 빈 배열 전달 (0) | 2020.10.14 |
R로 빌드 된 모델 재사용 (0) | 2020.10.14 |