[디딤돌 C++] 63. 구성(COMPOSITION) 관계

구성 관계는 소유 개체와 피 소유 개체 사이의 관계입니다. 이러한 관계는 집합 관계도 마찬가지입니다. 두 가지 관계 모두 “가지다.”로 표현할 수 있으며 영어로 “Has a”로 표현할 수 있어서 “Has a”관계라고 말합니다.

집합 관계는 소유 개체와 피 소유 개체의 생성과 소멸은 독립적으로 진행합니다. 필통과 연필의 관계처럼 개체의 생성과 소멸은 독립적인 특징을 갖습니다. 구성 관계는 소유 개체를 생성할 때 피 소유 개체를 생성하고 소유 개체를 소멸할 때 피 소유 개체를 함께 소멸합니다. 사람과 눈의 관계처럼 소유 개체를 생성할 때 피 소유 개체도 함께 생성하고 소유 개체를 소멸할 때 피 소유 개체도 함께 소멸합니다.

CPP에서 구성 관계를 구현하는 방법은 크게 두 가지입니다. 하나는 소유 클래스에 피 소유 클래스 형식 변수를 멤버 필드로 선언하는 것입니다.

class Man
{
    Eye eyes[2];
};

그리고 다른 하나는 소유 클래스에 피 소유 클래스 형식 포인터 변수를 멤버 필드로 선언하고 생성자에서 피 소유 개체를 동적 생성하고 소멸자에서 피 소유 개체를 동적 소멸하는 것입니다.

class Man
{
    Eye *eyes[2];
};
Man::Man(void)
{
    eyes[0] =new Eye();
    eyes[1] = new Eye();
}
Man::~Man(void)
{
    delete eyes[0];
    delete eyes[1];
}

다음은 구성 관계에 속하는 사람과 눈의 관계를 코드로 표현한 것입니다.

//Eye.h
#pragma once
#include <iostream>
#include <string>
using namespace std;

class Eye
{    
    bool isopened;
    bool left;
public:
    Eye(bool left);
    void Close();
    void Open();
    void See();
    bool IsOpened()const;    
};
//Eye.cpp
#include "Eye.h"

Eye::Eye(bool left)
{    
    this->left = left;
    isopened = false;
}

void Eye::Close()
{
    if(isopened)
    {
        if(left)
        {
            cout<<"왼쪽 눈을 감다."<<endl;
        }
        else
        {
            cout<<"오른쪽 눈을 감다."<<endl;
        }
    }
}

void Eye::Open()
{
    if(isopened==false)
    {
        if(left)
        {
            cout<<"왼쪽 눈을 뜨다."<<endl;
        }
        else
        {
            cout<<"오른쪽 눈을 뜨다."<<endl;
        }
        isopened = true;        
    }
}

void Eye::See()
{
    Open();
    if(left)
    {
        cout<<"왼쪽 눈으로 보다."<<endl;
    }
    else
    {
        cout<<"오른쪽 눈으로 보다."<<endl;
    }
}

bool Eye::IsOpened()const
{
    return isopened;
}
//Man.h
#pragma once
#include "Eye.h"
class Man
{
    Eye *eyes[2];
public:
    Man(void);
    ~Man(void);
    void Sleep();
    void Walk();
    void Wink();
};
//Man.cpp
#include "Man.h"

Man::Man(void)
{
    eyes[0] =new Eye(true);
    eyes[1] = new Eye(false);
}
Man::~Man(void)
{
    delete eyes[0];
    delete eyes[1];
}
void Man::Sleep()
{
    cout<<"=== Sleep ==="<<endl;
    eyes[0]->Close();
    eyes[1]->Close();
}
void Man::Walk()
{
    cout<<"=== Walk ==="<<endl;
    eyes[0]->Open();
    eyes[1]->Open();
    eyes[0]->See();
    eyes[1]->See();
    cout<<"앞으로 가다."<<endl;
}

void Man::Wink()
{
    cout<<"=== Wink ==="<<endl;
    eyes[0]->Open();
    eyes[1]->Close();
}
//Program.cpp
#include "Man.h"
int main()
{
    Man *man = new Man();    
    man->Walk();
    man->Wink();
    man->Sleep();
    delete man;
    return 0;
}

▷ 실행 결과

=== Walk ===
왼쪽 눈을 뜨다.
오른쪽 눈을 뜨다.
왼쪽 눈으로 보다.
오른쪽 눈으로 보다.
앞으로 가다.
=== Wink ===
오른쪽 눈을 감다.
=== Sleep ===
왼쪽 눈을 감다.
오른쪽 눈을 감다.