1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/////////////
//대입 연산자//
////////////
 
class CCopyStudy {
public:
    CCopyStudy(int nParam) {
        m_pnData = new int;
 
        *m_pnData = nParam;
    }
    
    //얕은 복사의 오류를 범하지 않기 위해 값을 복사한 깊은 복사 형태//
    CCopyStudy(const CCopyStudy &rhs) {
 
        m_pnData = new int;
        
        *m_pnData = *rhs.m_pnData;
    }
 
    //단순대입 연산자를 사용했을시 얕은 복사 방지를 위한 코드 추가//
    CCopyStudy& operator=(const CCopyStudy &rhs) {
        
        *m_pnData = *rhs.m_pnData;
 
        return *this;
    }
    
    ~CCopyStudy() {
        delete m_pnData;
    }
 
    int GetData() {
        if(m_pnData != NULL) {
            return *m_pnData;
        }
        return 0;
    }
 
private:
    int *m_pnData = nullptr;
}
 
int main(void) {
    
    CCopyStudy a(10);
    
    //매개변수를 통한 복사//
    //얕은 복사를 방지 하기 위한 깊은 복사 형태를 주의 해야 됨//
    CCopyStudy b(a);
 
    //단순 대입 연산자를 사용 하게 될 경우 오류가 발생//
    //단순 대입 연산자는 얕은 복사를 사용하게 되어서 메모리 해제시 오류가 발생//
    //operator 단순 대입 연산자를 사용 해야 됨//
 
    CCopyStudy c(20);
    a = c;   //a.operator(c); //사용 방법이 2가지가 있음//
    
    
    
    return 0;
}
cs



캡슐화와 정보은닉의 개념이 헷갈릴수가 있다. 아래의 예를 통해서 캡슐화를 알아 보자


class Key

{

public:

void Key() 

{

cout<<"키를 꼽습니다."<<endl;;

}

};

class StartButton

{

public:

void Button()

{

cout<<"시동 버튼을 누릅니다."<<endl;

}

};

class Car

{

public:

void TakeKey(Key &key);

void TakeStartButton(StartButton &button);

};


int main(void)

{

Key key;

StartButton button;


Car car;

car.TakeKey(key);

car.TakeStartButton(button);


return 0;

}


위 코드는 간략하게 자동차 시동을 켜는 방법을 클래스다. 그러나 위 예제가 캡슐화가 무너진 대표적인 예다. 왜냐 하면 자동차는 항상 키,시동버튼 행동을 포함 하게 된다. 또한 눈으로 확인 가능 하기가 어렵다.


따라서 아래 코드 처럼 변경 하면 좋다.


class Key

{

public:

void Take() 

{

cout<<"키를 꼽습니다."<<endl;;

}

};

class StartButton

{

public:

void Take()

{

cout<<"시동 버튼을 누릅니다."<<endl;

}

};


class CarStart

{

private:

Key key;

StartButton btn;


public:

void Take()

{

key.Take();

btn.Take();

}

};


class Car

{

public:

void TakeCarStart(CarStart &start)

{

start. Take();

}

};

int main(void)

{

CarStart carStart;

Car car;

car. TakeCarStart(carStart);


return 0;

}


여기서 가장 중요한 것은 캡슐화의 범위를 결정 하는 일이 쉽지 않다는 것이다. 







먼저 어떠한 좌표를 저장 하는 클래스를 기본적으로 만들어 보자


class Point 

{

public:

int x;  //x 좌표는 0보다 커야 한다.

int y;  //y 좌표는 0보다 커야 한다.

}


int main(void)

{

Point p1 = {-2,4};

Point p2 = {3,5};


return 0;

}


위 코드를 보듯이 Point 멤버 변수 x,y를 public로 선언을 하는 바람에 어디서든 접근이 가능 하게 되어 버렸다. 따라서 0보다 작은 수를 실수로 저장이 되어 버리는 현상이 발견 되었다. 이 부분을 방지 하기 위해서 임의로 막아 주는 부분이 필요 하다.


Point.h 파일


class Point

{

private:

int x;

int y;


public:

      void InitMembers(int xpos,int ypos);

int GetX();

int GetY();


bool SetX(int xpos);

bool SetY(int ypos);

}


Point.cpp 파일


bool Point::InitMembers(int xpos,int ypos) 

{

if(xpos < 0 || ypos < 0)

{

return false;

}


x = xpos;

y = ypos;


return true;

}


int Point::GetX()

{

return x;

}

int Point::GetY()

{

return y;

}

bool Point::SetX(int xpos)

{

if(xpos < 0)

{

return false;

}

x = xpos;

return true;

}

bool Point::SetY(int ypos)

{

if(ypos < 0)

{

return false;

}

y = ypos;

return true;

}


위 코드 처럼 Point 멤버 변수 x,y를 숨겨서 개발자가 실수를 최대한 줄여 줄수 있게 하는 방법 입니다. 

또한 GetY(),GetX() 를 GetY() const ,GetX() const를 함으로써 더욱 안정성을 높여 주는 것도 하나의 방법이다.




참고 : http://plming.tistory.com/52


include <iostream>

using namespace std;

class Animal;

class AnimalDelegate{
public:
    virtual void onSound(Animal* pSender)=0;
    virtual void onWalk(Animal* pSender)=0;
};

class Animal{
private:
    AnimalDelegate* delegate;

public:

    Animal(){
        this->delegate = NULL;
    }

    void setDelegate(AnimalDelegate* delegate){
        this->delegate = delegate;
    }

    void sound(){
        if(this->delegate){
            this->delegate->onSound(this);
        }
    }

    void walk(){
        if(this->delegate){
            this->delegate->onWalk(this);
        }
    }
};



//개 : Delegate를 내부에 직접 구현
class Dog:public Animal, public AnimalDelegate{
public:
    Dog(){
        this->setDelegate(this);
    }

    void onSound(Animal* pSender){
        cout << "Dog: 멍멍!" << endl;
    }

    void onWalk(Animal* pSender){
        cout << "Dog: 개가 걷는다" << endl;
    }
};

//고양이 Delegate
class CatDelegate:public AnimalDelegate{
public:
    void onSound(Animal* pSender){
        cout << "Cat: 야옹~" << endl;
    }

    void onWalk(Animal* pSender){
        cout << "Cat: 고양이가 걷는다" << endl;
    }
};

//고양이
class Cat:public Animal{};


void main(){

    Dog dog;
    Cat cat;

    dog.sound();
    dog.walk();
    
    CatDelegate cdel;

    cat.setDelegate(&cdel);
    cat.sound();
    cat.walk();
    
    getchar();
}

+ Recent posts