디자인 : 부모 클래스로 다시 전화


13

자식으로 개체를 모델링 할 때 부모 클래스의 구성원으로 컴포지션을 통해 자식을 포함하는 것이 일반적입니다. 그러나 때때로 아이들은 부모에게 무언가를 말해야하고 부모의 기능을 호출해야합니다. C ++를 사용하여 어떻게이 작업을 수행 할 수 있습니까? 일부 옵션은 다음과 같습니다.

  1. 부모 클래스를 전역 클래스로 만들면 자식 개체가 부모 개체의 멤버 함수를 호출 할 수 있습니다.

  2. 부모 객체를 모든 자식 객체에 포인터, 참조로 삽입하십시오. 그런 다음 자식이 부모 개체에 무언가를 말해야 할 때 사용할 수있는 멤버 변수가 있기 때문에 항상 그렇게 할 수 있습니다.

이 작업을 수행하는 다른 방법은 무엇입니까? 이런 종류의 디자인에 대한 일반적인 디자인 패턴이나 이름이 있습니까?

세부 사항이 다른 객체 지향 언어와 다를 수 있기 때문에 C ++의 아이디어와 솔루션에 관심이 있습니다. 예를 들어 위의 포인트 2는 '포인터 또는 참조'를 언급하고 C ++에서만 가능합니다. C ++에는 다른 언어에는없는 언어 기능이 있으므로 문제에 대한 솔루션을 구현하면 이러한 언어 기능을 통합하여 다른 언어에서 다른 언어로 솔루션을 만들 수 있습니다.


예를 추가 할 수 있습니까? 이것이 귀하의 질문에 대한 유효한 예입니까? orderitems (자식)가있는 orderobject (= parent)가 있고 orderitem-quantity가 변경 될 때 주문 총계를 업데이트 하시겠습니까? 아니면 완전히 다른 것을 생각하고 있습니까?
k3b

@ k3b 그래, 그것은 유효한 예입니다. 자녀의 일부 정보가 변경되어 부모가 무언가를하도록 요구했습니다.
sashang

생성자 매개 변수와 참조 데이터 멤버를 각 자식 클래스에 추가하십시오.
tp1

아이는 부모에 관한 모든 것을 알아야합니까, 아니면 간단한 것만 delegate으로 충분합니까?
Julien Guertault

답변:


16

우선, 코드 냄새가 날 수 있습니다. 부모 / 자녀에게 작문을 사용하는 요점은 부모가 자녀에 대해 알고 있지만 그 반대는 아님입니다. 특히 관계가 '구성'보다 '포함'에 더 많은 경우.

부모에 대한 참조는 C ++에서 가능하며 상당히 일반적입니다. 다른 언어로, 함수 객체 또는 이벤트는 외부인이 알고 싶어 할 수있는 것을 의사 소통하기 위해 더 자주 사용됩니다. 이것은 일반적인 발행-구독자 종류의 패턴입니다. 더 관용적 인 것은 사용중인 C ++ 버전과 코드베이스의 표준에 달려 있다고 생각합니다.


내 상황에서는 코드 냄새입니다. 좋은 대답입니다.
Martin Pfeffer

3

다른 사람들이 지적했듯이 부모 객체를 포인터 또는 참조로 삽입하는 기본 아이디어는 원칙적으로 진행하는 방법입니다.

여기에는 한 가지 단점이 있습니다. 부모와 자식 사이에 주기적 종속성이 있습니다. 이를 피하려면 IParent부모가 상속 하는 추상 기본 클래스 (인터페이스) 를 정의 하십시오. IParent자식이 호출하려는 가상 함수로 메소드를 포함해야합니다. 그런 다음에 대한 참조로 부모를 주입하십시오 IParent. 그러면 모의 객체로 부모 객체를 쉽게 대체 할 수 있기 때문에 단위 테스트가 훨씬 쉬워집니다.

자녀가 부모 개체의 함수 하나만 호출해야하는 경우 전체 IParent클래스가 너무 커질 수 있습니다. 이 경우 멤버 함수에 대한 포인터를 자식 함수 또는 해당 멤버 함수를 캡슐화하는 functor 객체에 삽입하면 충분합니다.


2

당신이 할 수있는 일은 작곡에 따라 자식 클래스의 부모에 대한 참조를 유지하는 것입니다. 그렇게하면 아이는 부모를 알고 그에 대한 공개 메소드를 호출 할 수 있습니다.

따라서 옵션 2를 사용하겠습니다. 부모에서 자식을 제거 할 때 자식의 부모에 대한 참조를 제거하고 null (또는 새 부모가있는 경우)을 가리켜 야합니다. 하나). 또는 컨텍스트에 따라 자식 개체를 간단히 삭제할 수 있습니다.


1

부모에게 참조 또는 포인터를 전달하십시오. 부모의 친구로 만들거나 호출 된 메소드를 공개 할 수 있습니다. 위의 방법 중 하나를 원하지 않으면 부모의 메서드 중 하나를 공개로 노출하고 그 자체가 부모의 고유 한 중첩 클래스 인 "브리지"개체를 전달할 수 있습니다 (따라서 모든 부모 메서드에 액세스 할 수 있음) ). 그러나 이것은 많은 상황에서 너무 복잡 할 수 있습니다.


1

2) 부모 객체를 모든 자식 객체에 포인터, 참조 또는 참조로 주입하십시오. 그런 다음 자식이 부모 개체에 무언가를 말해야 할 때 사용할 수있는 멤버 변수가 있기 때문에 항상 그렇게 할 수 있습니다.

완벽하게 실행 가능한 옵션입니다. 모든 현대 언어에는 다른 언어를 나타내는 데 사용할 수있는 기능이 있습니다.


1

약간의 변형이 있지만 비슷한 장점이 있습니다.

부모 A에 구성 요소 C가 있다고 가정하십시오.

컴포넌트 C에서 InterfaceC를 선언하고 이에 대한 참조를 보유하십시오. 이것은 외부 세계와 구성 요소의 인터페이스입니다.

부모 A는 InterfaceC를 구현하고 구성 요소 C에서 참조를 설정합니다. 구성 요소 C는 부모 A를 InterfaceC로 간주합니다.

아이디어는 다음과 같습니다. 구성 요소는 인터페이스를 사용하여 외부와 통신합니다.

부모를 직접 설정하는 것보다 이것을 사용하면 다음과 같은 장점이 있습니다.

구성 요소가 무언가를 수행하고 부모에게 알려야한다고 가정하십시오. 인터페이스를 호출합니다. 나중에 부모를 변경하기로 결정했습니다. 구성 요소는 전혀 신경 쓰지 않으며 변경하지 않습니다.

나중에 많은 객체에 이벤트를 알리고 싶다고 말하십시오. InterfaceC 목록을 작성하고 이에 대한 참조를 추가하기 만하면됩니다.

단점 : 부모 클래스는 많은 인터페이스를 구현하게 될 것입니다 (클래스 선언을 살펴보면 누가 그것에 대해 이야기하는지 즉시 알기 때문에 이점이라고 생각합니다)


0

이것은 C #에 따라 다릅니다. C ++에 비슷한 것이 있는지 모르겠습니다.

푸시 버튼이있는 gui-form이있는 경우 일반적 으로 Observer_pattern 또는 Publish-subscribe pattern 이라고도 하는 Event-Subscribtion을 사용하는 다른 접근 방식이 있습니다.

푸시 버튼은 공식적으로 그것이 사는 특정 형태를 알지 못한다. 대신 버튼 이 이벤트를 트리거하거나 게시 하면 양식에 가입 된 알림이 수신되고 이에 따라 반응 할 수 있습니다.

gui-s 외에도이 메커니즘은 모든 paren-child-relation에서 사용될 수 있습니다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.