2010-02-11 3 views
3

나는 이상하게 생각하고 있었다 :트리의 노드에 다중 상속이 허용됩니까?

나무로, 뿌리에는 다수 아이들 및 ID 없음이있을 수있다. 모든 노드 (루트 제외)는 ID를 가지며 리프 노드는 하위 노드를 가질 수 없습니다. 각 깊이에 대해 사용해야하는 유형이 고정되어 있습니다. 따라서 나뭇잎은 항상 같은 유형이므로 나뭇잎의 부모도 마찬가지입니다.

루트와 노드가 아이들과있을 수 있기 때문에에만 다중 상속의 다음 사용이 허용되는 경우 노드가 궁금 id를 가지고 :

class NodeWithId 
{ 
    private: 
     std::string m_id; 
}; 

template<typename T> 
class NodeWithChildren 
{ 
    private: 
     std::vector<T> m_nodes; 
}; 

class Network: public NodeWithChildren<Subnet> 
{ 
}; 

class Subnet: public NodeWithChildren<Machine>, 
        public NodeWithId 
{ 
}; 

class Machine: public NodeWithChildren<Application>, 
       public NodeWithId 
{ 
}; 

class Application: public NodeWithId 
{ 
}; 

또는이를 구현하는 더 나은 방법이?

편집 :

  • 제거 가상
  • 변경 클래스 이름
  • 모든
+1

왜 가상 계승을 사용하고 있습니까? 어떤 상속 경로에도 공유 기본 클래스가 없습니다. –

+2

모든 종류의 노드에 대해 하나의 클래스를 사용하고 리프의 빈 자식 벡터를 사용합니다. – Manuel

+1

마누엘에 동의합니다. ID에 -1 또는 0 또는 다른 예약 된 값을 사용합니다. 뿌리 내리고 디자인을 단순화하십시오. – Bill

답변

2

을 보인다 또는이를 구현하는 더 좋은 방법이 있나요?

IMHO를 사용하면 디자인을 통해 개체 인스턴스로 가장 잘 처리되는 클래스가 만들어집니다. 클래스 레벨에서는 Level1 노드와 Level2 노드를 구별 할 필요가 없습니다.

간단한 디자인을 사용하십시오. 이 디자인에 하나의 Node 클래스가 있고 Node 인스턴스 (실행시에 작성)의 트리 구조를 만드는 단순한 접근 방식보다이 잠재적 인 이점이 있는지 또는 스스로에게 질문하십시오.

+0

타입 안전? 트리의 모든 것이 노드 인 경우 각 노드의 유형을 동적으로 확인해야합니다. – rve

+0

@rve : 왜 '노드'의 유형을 확인해야합니까? 트리에서 실행할 작업/알고리즘에 대한 아이디어가 도움이 될 것입니다. – dirkgently

+0

예를 들어 네트워크에있는 PC와 같이 시스템을 설명하는 데이 시스템을 사용하고 싶습니다 (실제 시나리오는 비슷하지만 더 복잡합니다). 따라서 루트 노드는 단지 루트입니다. 루트의 하위 노드는 서브넷, 서브넷 하위는 머신, 시스템의 하위 노드는 응용 프로그램 및 리프입니다. 예를 들어 루트에 응용 프로그램을 추가하지 못하게하고 싶습니다. 그리고 확실한 (동적 유형 검사없이) 기계의 하위 항목을 가져 오는 경우 응용 프로그램입니다. – rve

1

첫째, 당신은 게시 된 샘플 코드를 기반으로 가상 상속에 대한 필요도 없다, 더 'dreaded diamond 없다 '

하지만 실제로 디자인을 전혀 얻지는 못했지만 트리를 대표하는 것에 대한 공통 기본 클래스는 없습니다. 왜 당신은 inherit을 사용하고 있습니까? 전혀 itance? 모든 것을 구성을 사용하여 얻을 수있는 것 같습니다.

이 질문에 대한 귀하의 계층 구조가 단순한 슬림 다운 버전입니까?

+0

음, 일부 노드는 자식을 가질 수 있으며이 자식 목록을 관리하는 코드는 모든 노드 (휴가 노드 제외)에서 동일하기 때문에 기본 클래스에있을 수 있습니다. 예, 가상 상속에 대한 권리가 있습니다. 작곡을 통해이를 수행하는 방법에 대한 예를 들려 줄 수 있습니까? – rve

2

당신은 단일 상속와 함께 할 수있는 :

class NodeWithId 
{ 
    private: 
     std::string m_id; 
}; 

template<typename T> 
class NodeWithChildren : public NodeWithId 
{ 
    private: 
     std::vector<T> m_nodes; 
}; 

class Root: public NodeWithChildren<Level1Node> 
{ 
}; 

class Level1Node: public NodeWithChildren<Level2Node> 
{ 
}; 

class Level2Node: public NodeWithChildren<LeafNode> 
{ 
}; 

class LeafNode: public NodeWithId 
{ 
}; 

당신은 당신이 ID가없는 NodeWithChildren을 가질 수있는 경우 다중 상속을하기 만합니다. 위의 디자인에서 모든 NodeWithChildren에는 NodeWithId도 포함되어 있으므로 NodeWithId에서 NodeWithChildren을 파생시킬 수 있으며 잠재적 인 다중 상속 문제를 완전히 무시할 수 있습니다.

은 ... 나에게 "더 나은"같은 디자인

+0

하지만 그 다음에는 뿌리에 더미 ID를 부여해야합니다. – rve

+0

나는 그것을 놓쳤다는 것을 인정하지만 그것은 나쁜 것 같지 않다 ... – Goz

-1

성능이 견딜 수 없을 정도로 뛰어나고 코드가 믿을 수 없을 정도로 복잡합니다.

먼저 각 노드에 벡터가 들어있는 템플릿을 사용합니다.

벡터만으로도 작업 속도가 크게 저하됩니다. 물건을 캐스팅하는 것은 트래버스 코드를 매우 느리게 만들 것이고 코드 자체는 다른 누구에게나 이해하기 어려울 것입니다.

또한 클래스가 다르므로 벡터는 어떻게 처리 할 수 ​​있습니까? 답변, 할 수 없습니다. 즉, 기본 클래스에 대한 포인터의 벡터 여야합니다. 그런 다음 런타임에 적절한 유형이 무엇인지 알아 내야합니다.

몇 가지 이점이 추가 된 경우 일부 용도에 유용 할 수 있지만 트리와 같은 구조에서 원하는 것과 반대입니다. 사용하기 쉽고 이해하기 쉽도록해야합니다. 가능한 적은 메모리 할당과 이상적인 성능.

관련 문제