4. 2 집합(Aggregation) 과 구성(Composition)
학생과 책의 관계처럼 "철수라는 학생은 책을 가지고 있다."라는 논리적 관계를 집합이라 합니다. 집합 관계에서는 소유 개체와 피 소유 개체의 생성 시기와 소멸 시기가 같지 않아도 됩니다. 이와 같은 관계에서 대부분 소유 개체가 피 소유 개체의 메서드를 호출하여 명령하는 직접 연관 관계가 존재하는 경우와 단순히 피 소유 개체들을 보관하는 집합체일 수 있습니다. 집합체일 경우에는 집합 관계만 표시하겠지만 직접 연관 관계가 존재하는 경우에는 집합 관계와 직접 연관 관계도 같이 표현하는 것이 좀 더 정확한 표현입니다.
[그림 4.2]는 집합 관계만 있는 경우이고 [그림 4.3]은 집합 관계에 직접 연관 관계도 있는 경우입니다.
[그림 4.2]
[그림 4.3]
Stu.h - 소유 클래스 |
#pragma once #include "Book.h" #define MAX_BOOKS 1000 class Stu { string name; Book *books[MAX_BOOKS]; int bcnt; public: Stu(string _name); bool PushBook(Book *book); Book *GetAt(int index); int GetBCnt()const; void View()const; }; |
Stu.cpp |
#include "Stu.h" Stu::Stu(string _name):name(_name),bcnt(0) //비 상수 멤버 필드도 초기화 기법 사용 가능함 { } bool Stu::PushBook(Book *book) { if(bcnt < MAX_BOOKS) { books[bcnt] = book; bcnt++; return true; } return false; } Book *Stu::GetAt(int index) { if((index>=0)&&(index<bcnt)) { return books[index]; } return 0; } int Stu::GetBCnt()const { return bcnt; } void Stu::View()const { cout<<"학생 이름:"<<name<<endl<<"갖고 있는 책 수:"<<bcnt<<endl; for(int i = 0; i<bcnt ; i++) { books[i]->View(); } } |
Book.h – 피 소유 클래스 |
#pragma once #include <iostream> #include <string> using std::cout; using std::endl; using std::string; class Book { string name; public: Book(string _name); ~Book(void); void View()const; };
|
Book.cpp |
#include "Book.h"
Book::Book(string _name) { name = _name; }
Book::~Book(void) { } void Book::View()const { cout<<"도서명:"<<name<<endl; } |
다음의 예제 코드를 보면 소유 개체와 피 소유 개체가 생성되는 과정과 소멸하는 과정이 종속적이지 않은 형태를 지니고 있음을 확인할 수 있습니다. 이와 같은 집합 관계는 C언어로 프로그래밍할 때에도 자주 표현하는 관계입니다.
Test.cpp |
#include "Stu.h"
void main() { Stu *stu = new Stu("홍길동"); Book *book = new Book("언제나 휴일"); if(stu->PushBook(book)) { cout<<"보관 성공"<<endl; } else { cout<<"보관 실패"<<endl; } stu->View();
delete stu; delete book; } |
그리고 사람과 팔의 관계처럼 "사람은 팔을 가지고 있다."라는 논리적 관계를 구성이라 합니다. 구성 관계에서는 피 소유 개체의 생성과 소멸이 소유 개체의 생성과 소멸에 종속적인 것이 집합 관계와의 차이점입니다. 광의적 의미로 얘기할 때 구성은 집합의 개념까지 포함해서 얘기합니다.
[그림 4.4]
위의 관계에 따라 Man 클래스를 정의할 때 내부에 멤버 필드를 Arm *arm; 혹은 Arm arm;으로 지정할 수 있을 것입니다. 만약, Arm *arm;과 같이 정의하였다면 생성자에서 arm 개체를 생성하고 소멸자에서 arm 개체를 소멸하는 코드가 구현되어 있을 때 구성 관계라 할 수 있습니다.
Man.h |
#pragma once
#include <string> using std::string;
#include "Arm.h"
class Man { string name; Arm *arm; public: Man(string _name); ~Man(void); };
|
Man.cpp |
#include "Man.h"
Man::Man(string _name) { name = _name; cout<<name<<"개체 생성"<<endl; arm = new Arm(); } Man::~Man(void) { cout<<name<<"개체 소멸"<<endl; delete arm; } |
Arm.h |
#pragma once #include <iostream> using std::cout; using std::endl; class Arm { public: Arm(void); ~Arm(void); }; |
Arm.cpp |
#include "Arm.h" Arm::Arm(void) { cout<<"Arm 생성자"<<endl; } Arm::~Arm(void) { cout<<"Arm 소멸자"<<endl; } |
Test.cpp |
#include "Man.h" void main() { Man *man = new Man("홍길동"); delete man; } |
[그림 4.5]
(모든 동영상 강의는 무료입니다.)
'언어 자료구조 알고리즘 > Escort C++' 카테고리의 다른 글
[C++] 파생 개체 생성 과정 및 초기화 (0) | 2016.04.15 |
---|---|
[C++] 일반화 관계와 파생 (0) | 2016.04.15 |
[C++] 실현관계 (Realization) (0) | 2016.04.15 |
[C++] 의존 관계 (Dependency) (0) | 2016.04.15 |
[C++] 연관(Association) 관계와 직접 연관(Directed Association) 관계 (0) | 2016.04.15 |
[C++} 4. 1 일반화 (Generalization) 관계 (0) | 2016.04.15 |
[C++] 캡슐화 실습 소스 코드 (0) | 2016.04.15 |
[C++] 캡슐화 실습 - 멤버 메서드 구현 (0) | 2016.04.15 |
[C++] 캡슐화 실습 - 테스트 모듈 작성하기 (0) | 2016.04.15 |
[C++]정적 멤버로 구성된 클래스 사용하기 (0) | 2016.04.15 |