1. 생성 패턴(Creational pattern)이란?
 인스턴스를 만드는 절차를 추상화하는 패턴입니다. 이 범주에 해당하는 패턴은 객체를 생성&합성하는 방법이나 객체의 표현 방법과 시스템을 분리해 줍니다. 클래스 생성 패턴이 인스턴스로 만들 클래스를 다양하게 만들기 위한 용도로 상속을 사용하는 반면, 객체 생성 패턴은 인스턴스화 작업을 다른 객체에게 떠넘길 수 도 있습니다.
 생성 패턴은 시스템이 어떤 구체 클래스를 사용하지에 대한 정보를 캡슐화합니다. 그리고 생성 패턴은 이들 클래스의 인스턴스들이 어떻게 만들고 어떻게 서로 맞붙는지에 대한 부분을 완전히 가려줍니나. 결론적으로, 생성 패턴을 이용하면 무엇이 생성되고, 누가 이것을 생성하며, 이것이 어떻게 생성되는지, 언제 생성할 것인지 결정하는데 유연성을 확보할 수 있게 됩니다.

2. 예제로 보는 패턴들....
[[ 미로게임 ]]
§ 전제
- 단순히 미로에서 빠져나오는 게임일 때는 전체 미로 중 플레이어에게 보이는 만큼의 미로가 표시 됨.
- 풀어야 할 문제가 있을 수도 있고, 극복해야 할 위험이 숨겨진 미로게임일 때는 미로의 일부분에 해당하는 평면 지도가 제공되기도 함.
- 복잡한 미로게임을 다루지는 않음.
- 플레이어가 ( 1..* )임.
- 미로는 방들의 집합이고 각 방은 옆에 무엇이 있는지도 알 수 있음.
- 방 옆에 방
- 방 옆에 문
- 방 옆에 벽

§ 클래스도

( C++  구현시 )
- 각 방은 네 개의 뱡향을 갖는데,,,
MapSite 클래스는 미로의 구성요소들에 필요한 모든 연산을 정의한 공통 추상 클래스
 
Room 클래스는 MapSite를 상속받은 구체적인 클래스로 미로에 있는 다른 요소와 관련성을 갖도록 정의합니다. 
Door과 Wall 클래스
- 또한 방들의 집합을 표현하기 위해서 클래스 Maze를 정의

-  MazeGame이란 클래스가 필요합니다.
   실제로 미로를 생성하는 클래스로 일련의 연산을 통해 빈 미로에 미로의 구성요소를 추가하고 이들을 연결하는 것입니다.

위 CreateMaze()가 갖고 있는 문제는 유연성이 떨어진다는 것이다. 즉, Room 클래스의 생성자에 변경되는 아래 부분만 코드화하면 된다!
r1->SetSide(East, theDoor);
r2->SetSide(West, theDoor);
(흠... 위 소스코드는 타이핑 하는데.. 자연스럽게.. Ctrl+C / Ctrl+V 를 이용하고 있는 제 자신을 발견하고...놀랐다는;;)
생성패턴은 이런 상황에서 어떻게 유연한 설계를 할 수 있는지에 대한 해법을 제공합니다.


지금 시점에서 가장 큰 장애 요인은 클래스들의 인스턴스를 직접 생성하도록 하드코딩한다는 점입니다.
- CreateMaze가 방, 벽, 문을 생성하기 위해서 생성자를 이용하지 않고 가상 함수를 호출하도록 구현되어 있다면, 이 가상 함수의 실제구현을 다양한 방법으로 변경할 수 있을 것입니다. <<팩토리 메소드 패턴>>
- CreateMaze가 방, 벽, 문을 생성하기 위해 생성 방법을 알고 있는 객체를 매개변수로 넘겨받을 수 있다면, 생성 방법이 바뀔 때 마다 새로운 매개변수를 넘겨받음으로써 생성할 객체의 유형을 달리할 수 있습니다. <<추상 팩토리 메소드 패턴>>
- CreateMaze가 생성하고자 하는 미로에 방, 문, 벽을 추가하는 연산을 사용해서 새로운 미로를 만들 수 있는 객체를 넘겨받는다면 미로를 만드는 방법이나 변경을 이 객체의 상속을 통해서 해결할 수 있습니다. <<빌더 패턴>>
- CreateMaze를 이미 만든 다양한 방, 문, 벽 객체로 매개변수화하는 방법도 가능한데, 이미 만든 객체를 복사해서 미로에 추가하면, 이들 인스턴스를 교체하여 미로의 복합 방법을 변경할 수 있습니다. <원형 패턴>

cf) 단일체 패턴은 한 게임에 오로지 하나의 미로 객체만 존재할 수 있고 그 게임에서 돌아가는 모든 게임 객체들이 이 미로에 접근이 가능하도록 보장합니다. 전역 변수나 전역 함수에 의존할 필요 없이 이런 일이 가능합니다. 또한 단일체 패턴은 기존 코드를 건드리지 않고도 미로를 쉽게 대체하거나 확장할 수 있도록 해 줍니다.




0. 시작하기
 설계는 지금 당장 갖고 있는 문제를 해결할 수 있어야 하지만, 나중에 생길 수 있는 문제나 추가된 요구 사항들도 수용할 수 있도록 일반적이고 포괄적이어야 합니다. 즉, 재설계를 하지 않아도 다시 사용할 수 있어야 하고, 아니면 가능한 최소한의 수정을 통해서 다시 사용할 수 있는 설계여야 합니다.

1. 디자인 패턴이란?
 디자인 패턴은 "특정한 전후 관계에서 일반적 설계 문제를 해결하기 위해 상호교류하는 수정 가능한 객체와 클래스들에 대한 설명"입니다.
 디자인 패턴은 설계자로 하여금 재사용이 가능한 설계는 선택하고, 재사용을 방해하는 설계는 배제하도록 도와주며, 패턴을 쓰면 이미 만든 시스템의 유지보수나 문서화도 개선할 수 있고, 클래스의 명세도 정확하게 할 수 있으며, 객체 간의 상호작용 또는 설계의 의도 등까지 명확하게 정의할 수 있습니다.

▷  생성 패턴은 객체의 생성 과정에 관여하는 것
생성 클래스 패턴은 객체를 생성하는 책임의 일부를 서브클래스가 담당
생성 객체 패턴은 이를 다른 객체에게 위임.
▷ 구조 패턴은 클래스나 객체의 합성에 관한 것
구조 클래스 패턴은 상속을 이용해서 클래스를 복합
구조 객체 패턴은 객체를 합성하는 방법을 정의
▷ 행동 패턴은 클래스나 객체들의 상호작용하는 방법과 책임을 분산하는 방법을 정의
행동 클래스 패턴은 상속을 이용해서 알고리즘과 제어 흐름을 기술
행동 객체 패턴은 하나의 작업을 수행하기 위해 객체 집합이 어떻게 협력하는지를 기술

    

목적
생성
구조
행동

범위
클래스
팩토리 메서드
(Factory Method)
적응자(Adapter class)
해석자(Interpreter)
템플릿 메서드
(Template Method)
객체
추상 팩토리(Abstract Factory)
빌더(Builder)
원형()
단일체
적응자(Adapter object)
가교(Bridge)
복합체(Composite)
장식자(Decorator)
퍼사드(Facade)
플라이급(Flyweight)
프록시(Proxy)
책임 연쇄
(Chain of Responsibilty)
명령(Command)
해석자(Interpreter)
중재자(Mediator)
반복자(Iterator)
메멘토(Memento)
감시자(Observer)
상태(State)
전략(Strategy)
방문자(Visitor)

<표1> 디자인 패턴 영역


<그림 1> 디자인 패턴 관계도

2. 디자인 패턴이 필요한 이유?
1) 특정 클래스에서 객체 생성
 객체를 생성할 때 클래스 이름을 명시하면 어떤 특정 인터페이스가 아닌 어떤 특정 구현에 종속됩니다. 이런 종속은 앞으로의 변화를 수용하지 못합니다. 이를 방지하려면 객체를 직접 생성해서는 안됩니다.
(디자인 패턴 : 추상 팩토리, 팩토리 메서드, 원형)

2) 특정 연산에 대한 의존성
 특정한 연산을 사용하면, 요청을 만족하는 한 가지 방법에만 매이게 됩니다. 요청의 처리 방법을 직접 코딩하는 방법을 피하면, 컴파일 시점과 런타임 모두를 만좃하면서 요청 처리 방법을 쉽게 변경할 수 있습니다.
(디자인 패턴 : 책임 연쇄, 명령)

3) 하드웨어와 소프트웨어 플랫폼에 대한 의존성
 기존에 존재하는 시스템 인터페이스와 응용프로그래램 프로그래밍 인터페이스는 소프트웨어 및 하드웨어 플랫폼마다 모두 다릅니다. 특정 플랫폼에 종속된 소프트웨어는 다른 플랫폼에 이식하기도 어렵고요. 또한 본래의 플랫폼에서도 버전의 변경을 따라가기 어려울 수 도 있습니다. 이런 플랫폼 종속성을 제거하는 것은 시스템 설계에 있어 매우 중요합니다,.
(디자인 패턴 : 추상 팩토리, 가교)

4) 객체의 표현이나 구현에 대한 의존성
 사용자가 객체의 표현 방법, 저장 방법, 구현 방법, 존재의 위치에 대한 모든 방법을 알고 있다면 객체를 변경할 때 사용자도 함"께 변경해야 합니다. 이런 정보를 사용자에게 감춤으로써 변화의 파급을 막을 수 있습니다.
(디자인 패턴 : 추상 팩토리, 가교, 메멘토, 프록시)

5) 알고리즘 의존성
 알고리즘 자체를 확장할 수도, 최적화할 수도, 다른 것으로 대체할 수도 있는데, 알고리즘에 종속된 객체라면 알고리즘이 변할 때마다 객체도 변경해야 합니다. 그러므로 변경이 가능한 알고리즘은 분리해 내는 것이 바람직합니다.
(디자인 패턴 : 빌더, 반복자, 전략, 템플리 메서드, 방문자)

6) 높은 결합도
 높은 결합도를 갖는 클래스들은 독립적으로 재사용하기 어렵습니다. 높은 결합도를 갖데 되면 하나의 커다란 시스템이 되어 버립니다. 이렇게 되면 클래스 하나르 수정하기 위해서 전체를 이해해야 하고 다른 많은 클래스도 변경해야 합니다. 또한 시스템은 배우기도 힘들고, 이식은 커녕 유지보수하기 조차도 어려운 공룡이 되어 버립니다.
 약한 결합도는 클래스 자체의 재사용을 가능하게 하고 시스템의 이해와 수정, 확장이 용이해서 이식성을 증대시킵니다. 추상 클래스 수준에서 결합도를 정희한다거나 계층화시키는 방법으로 디자인 패턴은 낮은 결합도의 시스템을 만들도록 합니다.
(디자인 패턴 : 추상 팩토리, 가교, 책임 연쇄, 명령, 퍼사드, 중재자, 감시자)

7) 서브 클래싱을 통한 기능 확장
 객체 합성과 위임은 행동 조합을 위한 상속보다 훨씬 유연한 방법입니다. 기존 객체들을 새로운 방식으로 조합함으로써 새로운 서브클래스를 정의하지 않고도 응용프로그램에 새로운 기능성을 추가할 수 있습니다. 한편, 객체 합성을 많이 사용한 시스템은 이해하기가 어려워집니다. 많은 디자인 패턴에서는 그냥 서브클래스를 정의하고 다른 인스턴스와 새로 정의한 클래스의 인스턴스를 합성해서 기능을 재정의하는 방법을 도입합니다.
(디자인 패턴 : 가교, 책임 연쇄, 장식자, 감시자 , 전력)

8) 클래스 변경이 편하지 못한 점
 가끔 클래스를 변경하는 작업이 그렇게 단순하지 않을 때가 많습니다. 소스 코드가 필요한데 없다고 가정해 봅시다. 또한 어떤 변경을 하면 기존 서브클래스의 다수를 수정해야 한다고 가정합시다. 디자인 패턴은 이런 환경에서 클래스를 수정하는 방법을 제시합니다.
(디자인 패턴 : 적응자, 장식자, 방문자)

3. 디자인 패턴을 고르는 방법
- 패턴이 어떻게 문재를 해결하는지 파악합시다.
- 패턴의 의도 부분을 봅시다.
- 패턴들 간의 관련성을 파악합시다.
- 비슷한 목적의 패턴들을 모사어 공부합시다.
- 재설꼐의 원인을 파악합시다.
- 설계에서 가변성을 가져야 하는 부분이 무엇인지 파악합시다.

4. 디자인 패턴을 통해 다양화 할 수 있는 설계 측면

 목적
디자인 패턴  
이 패턴을 통해 다양화 할 수 있는 부분
생성
 추상 팩토리 (Abstract Factory)
 제품 객체군
 빌더(Builder)
 복합 객체 생성 방법
 팩초리 메서드(Factory Method)
 인스턴스화 될 객체의 서브클래스
 원형(Prototype)
 인스턴스화 될 객체의 클래스
 단일체(Singleton)
 클래스의 인스턴스가 하나일 때
구조
 적응자(Adapter)
 객체에 대한 인터페이스
 가교(Bridge)
 객체 구현
 복합체(Composite)
 객체의 합성과 구조
 장식자(Decorator)
 서브클래싱 없이 객체의 책임성
 퍼사드(Facade)
 서브시스템에 대한 인터페이스
 플라이급(Flyweight)
 객체의 저장 비용
 프록시(Proxy)
 객체 접근 비용
행동
 책임 연쇄(Chain of Responsibility)
 요청을 처리하는 객체
 명령(Command)
 요청을 처리 시점과 처리 방법  
 해석자(Interpreter)
 언어의 문법과 해석 방법
 반복자(Iterator)
 집합 객체 요소들의 접근 방법 및 순회 방법
 중재자(Mediator)
 어떤 객체들이 어떻게 상호작용하는지
 메멘토(Memento)
 어제 어떤 정보를 객체의 외부에 저장하는지
 감시자(Observer)
 다른 객체의 종속적인 객체 수
 종속적인 객체들의 상태 변경 방법
 상태(State)
 객체의 상태
 전략(Strategy)
 알고리즘
 템플릿 메소드(Template Method)
 알고리즘 단계   
 방문자(Visitor)
 클래스의 변경 없이 객체에 적용할 수 있는 연산

<표2> 디자인 패턴을 통해 다양화 할 수 있는 설계 측면




드디어 Class강좌를 쓰고 있자니 마음이 설레네요!
언제나 화이팅!

*이 강좌는 C언어를 끝냈다는 가정하에 실시합니다.

┌───────────────┐
---앞으로의 목차---
3-2. 객체에 대하여
3-3. 접근제어
3-4. 멤버함수의 외부정의
└───────────────┘

<지난 강좌를 살펴보고 와주세요 !! : http://blog.naver.com/owndks98o/120157307983 >

3-2. 객체에 대하여
이번시간에는 객체에 대한 이모저모를 알아보겠습니다.
어쩌면 상당히 따분한 이론수업이 될 수도 있으나, 객체의 기본을 다루는 꼭 필요한 부분이니
잘 익혀 두시기를 바랍니다.

먼저 데이터 추상화(Data Abstraction) 를 알아보도록 하겠습니다.
원래 지향하는 바라면, 제가 비유까지 해야 하나 워낙 난해한 부분이라 이 책의 내용을 인용하겠습니다.
(전 C++을 "열혈강의 C++프로그래밍"과 "누드 C++"에서 참고하였습니다.)

여러인디언이 있습니다. 문제는 그중에 단 한명만이 코끼리를 본적이 있기에, 그 인디언은 다른 인디언들에게 코끼리의 모양에 대해 설명해 주기 시작합니다.
"코끼리는 말이야. 일단 발이 네 개야. 그리고 코가 하나 있는데, 그 코의 길이가 한 5미터 정도는 되지. 그리고 그 코를 이용해서 목욕을 하기도 하고, 또 물건을 집기도 해. 아! 크기는 말이야. 글쎄 무개로 따지면 1톤은 족히 넘을 거야"

이 설명을 들은 인디언들은 이 코끼리를 머릿속에 정리할것입니다. 이렇게 말이죠!
  1. 발이 4개
  2. 코의 길이가 5미터 정도
  3. 몸무게 1톤정도
  4. 코를 이용하여 목욕
  5. 코를 이용하여 물건을 집음
이것을 프로그래밍에 비유하면 1,2,3 번은 데이터 적인 측면, 4,5번은 기능적인 측면입니다.
이렇듯,
"현실세계의 사물을 데이터적인 측면과 기능적 측면을 통해서 정의하는것"
이 데이터추상화(Data Abstraction)이라고 합니다.

그럼 이제 하나의 객체(Object)에 대해 프로그래밍에서 사용하기까지의 과정에 대한 용어를 알아보죠.

예를 들어, 먼저 "사람"이란 것을 프로그램 상에 옮길때에, 데이터 추상화를 하는 과정을 "추상화" 라고 합니다.
(갑자기 "사람"이란 단어가 너무나도 어색하게 느껴지는 군요;;)

 

그리고, 이 추상화한 것을 자료형으로 정의하는 것을 "클래스화"라고 합니다.

이것이 일반적으로 클래스를 정의할때에 사용되는 용어입니다.

클래스를 정의한다는 것은 일반적인 자료형(int,char,...)등을 정의하는 것과 같습니다.
따라서 클래스를 사용할떄에 클래스를 선언해줄 필요가 있습니다.
따라서, 이렇듯 클래스를 선언해주는 것을 "인스턴스화(instantiation)"한다 라고 표현합니다.


이번시간에는 여러 클래스에 대한 용어를 알아보았습니다.
다음강에서 만나도록 합시다~~!!




C++의 첫이름이 뭔지 아시나요?

 C with Class 였습니다.
그만큼 Class의 비중은 C++ 에서 크게 차지합니다.

그 Class의 시작을 향해!!

*이 강좌는 C언어를 끝냈다는 가정하에 실시합니다.

┌───────────────┐
---앞으로의 목차---
3-1. 구조체? 클래스?
3-2. 객체에 대하여
3-3. 접근제어
└───────────────┘

<지난 강좌를 살펴보고 와주세요 !! : http://blog.naver.com/owndks98o/120156950445 >

3-1. 구조체? 클래스?
클래스에 대해 이해하려면, 클래스의 Downgrade 버젼이라고 말할수 있는 구조체와의 연관이 필요합니다.
그러니 잠시 구조체에 대한 이야기를 하고 지나가 보죠.

구조체는 그 이름 그대로 구조적인 프로그래밍을 위해 태어났습니다.
프로그램이 커지며, 변수가 많아지고 그 변수들의 관리가 힘들어지기에, 그 변수들을 몇가지 기준에 따라 분류한 것이 구조체입니다.
따라서 구조체는 관련된 데이터를 묶기에도, 그 프로그래밍에도 편리하다 는 장점이 있습니다.

C++에는 이러한 구조체의 기능에도 +를 더해줍니다.
일반적인 C언어라면 아래와 같이 구조체를 정의할 것입니다.

typedef struct _Leanix{
char name[10];
int age;
}Leanix;

Leanix nx;

하지만 C++은 사용자가 정의했든, 언어자체적으로 정의했든 동일하게 대우해주자는 철학이 있습니다. 따라서,

struct Leanix{
char name[10];
int age;
};

Leanix nx;

처럼 정의하여도 오류가 나지 않습니다.

프로그램은, 흔히들 아래와 같이 이루어져 있다고 이야기합니다.
프로그램 = 자료구조 + 알고리즘
어렵게 느껴지신다고요?

그냥 변수와 그 변수를 관리하는 연산으로 이루어져 있다는 뜻입니다.

/*
StructAndFunction.cpp
*/
#include
using namespace std;

struct Dat{
int ndat;
char cdat;
};

void Set(Dat& dat,int nDat,char cDat){
dat.ndat=nDat;
dat.cdat=cDat;
}

void Init(Dat& dat){
dat.ndat=dat.cdat=0;
}

int main(){
Dat d;
Init(d);
Set(d,10,'d');
return 0;
}

위 소스에 비유하면, 구조체는 자료구조이고 함수는 알고리즘이 되는 것이죠.
하지만 이소스를 보면 영 거슬리는 부분이 있습니다.
왜 꼭 Dat함수의 레퍼런스를 넘겨야 하는 것일까요?
분명 Set과 Init는 구조체 Dat의 함수인데 왜 밖에 따로 선언되어있는 것일까요?

그러니 그냥 묶어 버립시다.
/*
StructOnly.cpp
*/
#include
using namespace std;

struct Dat{
void Set(int nDat,char cDat){
ndat=nDat;
cdat=cDat;
}
void Init(){
ndat=cdat=0;
}
int ndat;
char cdat;
};
int main(){
Dat d;
d.Init();
d.Set(10,'d');
return 0;
}
놀라운가요? 아직은 간단하게 이해합시다. Dat이라는 구조체 안에 함수가 존재하는 것이라고.
간단하죠? 그냥 함수를 구조체 안에 넣은것에 지나지 않습니다.

더욱 놀라운 것은, 이젠 Dat이 구조체가 아닌, 클래스라는 사실입니다.

"아니, struct를 사용했는데 클래스라고?" 라고 따지는 분이 있겠지요? 그럼,
"구조체 안에 함수가 있을수 있나요?" 라고 묻겠습니다.

즉 Dat은 클래스가 되는 것이며, 위의 빨간 부분에서 말했듯이,
"Class(클래스)=Attribute(특성-변수-) + Method(방법-함수-)"
가 되는 것입니다.
보통 Attribute를 가르켜 멤버변수라고 하며, Method를 가르켜 멤버함수라고 합니다.

그럼 이제 Dat을 완벽히 클래스로 바꿔봅시다.
/*
CDat.cpp
*/
#include
using namespace std;

class Dat{
public:
int ndat;
char cdat;
void Set(int nDat,int cDat){
ndat=nDat;
cdat=cDat;
}
void Init(){
ndat=cdat=0;
}
};
int main(){
Dat d;
d.Init();
d.Set(10,'d');
cout<<"ndat : "<
return 0;
}

어엇 아직은 모르는 부분이 남아있습니다. public: 등에 관한 것이지요.
서서히 배울테니 걱정마시기 바랍니다.

그리고 이젠, 클래스를 '객체' 라고 표현합니다.
하나의 완전한 대상체라고 여기는 것이죠.

그럼 다음강의에서 뵙도록 하죠!!




우왕 쿧! ㅋ;; 
드디어 2단원의 마지막이네요...

더욱 수고해 주시길 바랍니다!!
2단원으로써 C와 C++을 비교하는 챕터가 끝날 뿐이니까요 하핫!

*이 강좌는 C언어를 끝냈다는 가정하에 실시합니다.

┌───────────────┐
---앞으로의 목차---
2-6. new&delete
3-1. 구조체? 클래스?
3-2. 객체에 대하여
└───────────────┘

<지난 강좌를 살펴보고 와주세요 !! : http://blog.naver.com/owndks98o/120156814599 >

2-6. new&delete
안녕하세요!!
드디어 2단원의 마지막이라 그런지 저도 설레고 떨립니다 하핫;;

이번시간에는 malloc과 free를 C++에 어울리게 기능을 추가한 new와 delete에 대해 알아봅시다.
먼저 malloc과 free를 훑어보고 지나갈까요?

/*
malloc.cpp
*/
#include
using namespace std;

int main(){
const int size=16; //이정도 할당해 봅시다.

int* dat=(int*)malloc(sizeof(int)*size);

free(dat);
return 0;
}
이 정도 예제는 바로 이해할수 있을 것이라 생각합니다.

그럼 이 예제를 그대로 c++의 new와 delete 형식으로 바꿔보죠.
훨씬 간단해진 것을 볼수 있을 것입니다.

/*
new.cpp
*/
#include
using namespace std;

int main(){
cont int size=16;

int* dat=new int[size];
delete[] dat;
return 0;
}
훨씬 간단해진 것이 보이시나요?
소스의 붉은 부분을 보시면,
new 타입[...]
처럼 되있는 부분을 보실수 있으실겁니다.
이부분에서 타입형 데이터 ...개를 할당합니다.

만약 한개만을 할당하고 싶다면,
new 타입
으로 끝내실수 있습니다.

그리고 new의 거대한 장점!!
malloc은 void포인터를 리턴하기 때문에 강제형변환을 해주어야 했지만 new는 할필요가 없습니다.
int면 int* char이면 char*로 알아서 리턴해 주기 때문이죠.

그럼 이젠 반환해 봅시다.
delete[] 메모리;
처럼 되어있는 부분이 보이시나요?

이 부분에서 메모리를 반환하게 됩니다.

역시 한개만을 반환하고 싶다면,
delete 메모리;
로 끝내실수 있습니다.

그럼 만약 한가지 가정을 해봅시다. 만약 동적할당이 제대로 되지 않았다면?
으아아악 거리면서 프로그램이 종료되버리면 되는걸까요? <퍽퍽 죄송합니다;;

이런 상황을 대비하기 위하여 new는 동적할당이 되지 않았을 경우를 대비하여 안됬을때 NULL을 리턴합니다.
아래와 같은 소스를 짜보면 되는 것이죠.

/*
NULL.cpp
*/
#include
using namespace std;

int main(){
const int size=16;

int *dat=new int[size];
if(dat==NULL){
//종료전처리
return -1;
}

delete[] dat;
return 0;
}
간단하죠?

하지만 이러한 코드는 일반적으로 보았을때에 NULL이 리턴되는 경우가 잘 없으므로, 성능의 저하를 불러온다고 생각하시는 분들이 많이 있습니다. 따라서, 이러한 코드는 DEBUG 시에서만 작성하는 것도 하나의 방법이 될수 있습니다.
new&delete의 응용은 class를 배우면서 해보도록 합시다!

Tip.사실 new와 delete는 class관련해서 중요한 기능을 가지고 있습니다. 그건 다음 단원에서 알아봅시다 하핫!




흐흑...
정말 죄송합니다;;
요즘 내신관리에 바쁜 나머지...

  *이 강좌는 C언어를 끝냈다는 가정하에 실시합니다.

┌───────────────┐
---앞으로의 목차---
2-5. 레퍼런스와 함수 II
2-6. new&delete
3-1. 구조체? 클래스?
└───────────────┘
<지난 강좌를 살펴보고 와주세요 !! : http://blog.naver.com/owndks98o/120156014435 >
2-5. 레퍼런스와 함수 II 
이번시간에는 레퍼런스를 리턴하는 함수를 배워봅시다!

먼저 소스코드를 드릴테니 한번 분석해 볼까요?

 /*
ref_return.cpp
*/
#include
using namespace std;

int& add(int &mum){
mum++;
return mum;
}

int main(){
int num=10;
int &x=add(num);

cout<
cout<

return 0;
}

꽤나 간단한 소스입니다. 보시면 이해가 되실거라고 생각합니다.
딱! 하나 레퍼런스를 리턴하는 부분을 뺸다면 말이죠.

함수와 함수의 호출을 보시면, 호출할때에 num이라는 변수를 주면, mum이라는 이름을 하나 더 만듭니다.
int& add(int &mum){
그리고 mum을 return할때에 x라는 새로운 이름이 하나를 더 받게 됩니다.

즉, 이 함수에서는 num==mum==x 가 되는 것이죠.

따라서 이 프로그램의 실행결과는 11 11 이 되게 됩니다.

하지만 하나! 조심해야 할 부분이 있습니다.
바로 지역변수를 레퍼런스로 리턴하는 경우입니다.

 #include
using namespace std;

int& turn(){
int num=10;
return num;
}

int main(){
cout<
return 0;
}

이럴경우 과연 어떻게 될까요?
아~주 큰일이 생기게 됩니다.

지역변수인 num은 함수의 호출이 종료되면 메모리 공간에서 사라지게 됩니다.
그후 그 메모리는 다른 변수나 함수가 사용하게 되지요.

그런데, 그 값을 리턴할경우, 받는 main함수 쪽에서는 제대로된 메모리를 받지 못하게 될수도 있다는 뜻이 됩니다.

설사, 제대로된 값이 나온다 해도 프로그램이 조금만 더 복잡해 지면 바로 값이 바뀔것이라 장담합니다.

따라서,
절대 지역변수를 레퍼런스로 리턴하면 안됩니다.

그럼 다음강 new&delete에서 뵙겠습니다^^





오늘은 얼마나 할수 있으려나? ㅋ

시작해 봅시다!!

  *이 강좌는 C언어를 끝냈다는 가정하에 실시합니다.

┌───────────────┐
---앞으로의 목차---
2-4. 레퍼런스의 이용
2-5. 레퍼런스와 함수 II
2-6. new&delete
└───────────────┘

<지난 강좌를 살펴보고 와주세요 !! : http://blog.naver.com/owndks98o/120156012111 >

2-4. 레퍼런스의 이용 

저번시간에는 Call-By-Reference 에 대해 알아보았습니다.
이번에는 그와 상반되는 말인,
Call-By-Value 에 대해 알아보겠습니다.

먼저, Call-By-Value란,
"함수의 호출에서 전달인자에 메모리를 복사해서 넘겨주는 것"
등으로 정의할수 있겠군요.

간단한 예제로 강좌를 시작해 봅시다.

/*
cbv.cpp //call-by-value
*/
#include
using namespace std;

typedef struct _MemDat{
char Name[20];
char ID[20];
char PS[20];
int age;
}MemDat;

void Show(MemDat md);

int main(){
MemDat md;
cout<<"Name : ";
cin>>md.Name;
cout<<"ID : ";
cin>>md.ID;
cout<<"PS : ";
cin>>md.PS;
cout<<"age : ";
cin>>md.age;

Show(md);
return 0;
}

void Show(MemDat md){
cout<<"Name : "<
cout<<"ID : "<
cout<<"PS : "<
cout<<"age : "<
}

 Call-By-Value의 기본 방식은 메모리의 복사입니다.
따라서 이런 방식은 메모리를 그냥 낭비하는, 어쩌면 정말로 몰상식한 행위를 일으키게 됩니다.

그렇다면 레퍼런스를 이용하여서 문제점을 고치려면 어떻게 해야 할까요?
매우 간단합니다.

void Show(MemDat md){ ...
이 부분을,
void Show(MemDat &md){...
로 고쳐주면 되는 것이죠!!(선언과 정의 모두)

//cbv2.cpp 예제는 올려두겠습니다.

이렇게 하면 몇 바이트나 되는 데이터를 복사하지 않아도 되므로, 성능면에서도 메모리 면에서도 win-win할수 있습니다.

또한가지 TIP을 보고 넘어가보죠.
우리가 만든 이 함수는 단지 데이터를 보여주기만 하는 함수입니다.
따라서 데이터를 수정한다거나 그럴필요는 없죠.

따라서,
void Show(MemDat &md){...
이 부분을,
void Show(const MemDat &md){
로 고쳐주면 더욱 효율적인 코딩이 가능해 집니다.

그럼 다음강에서~~




으헝... 
월요병이 도져서... 또 길게 쉬다 왔네요...
본의 아니게...

시작합시다.

  *이 강좌는 C언어를 끝냈다는 가정하에 실시합니다.

┌───────────────┐
---앞으로의 목차---
2-3. 레퍼런스와 함수
2-4. 레퍼런스의 이용
2-5. 레퍼런스와 함수 II
└───────────────┘

<지난 강좌를 살펴보고 와주세요 !! : http://blog.naver.com/owndks98o/120155834133 >

2-3. 레퍼런스와 함수

이번강의에서는 레퍼런스의 강력한 장점을 알아보죠.

그에 앞서,
Call-By-Reference
란 말의 의미를 아세요?

C를 열심히 배우셨다면 아실거라고 믿어 의심치 않습니다만,
노파심에 다시 한번 설명해 드리자면, "함수를 호출할때에 전달인자를 복사하지 않고 넘겨주는 방식"
이라고 간결하게 설명할수 있을것 같습니다.

간단한 예제로 살펴보죠.

/*
swap_ptr.cpp
*/
#include
using namespace std;

void swap(int *a,int *b);

int main(){
int x=0,y=1;

cout<
swap(&x,&y);
cout<

return 0;
}

void swap(int *a,int *b){
int temp=*a;
*a=*b;
*b=temp;
}

포인터를 이용한 간단한 swap함수의 예제입니다.
하지만, 이 소스는 포인터를 이용했기에, 치명적인 문제가 있습니다.

바로,
"포인터 연산의 실수 에 따라 발생하는 문제"
이죠.

포인터는 주소값을 가지고, 메모리를 직접참조하는 C만의 기법이기 때문에, 자칫 연산의 실수가 일어나면 프로그램 전체가 종료 될만큼 위협적인 에러를 자랑합니다.

그래서 포인터의 연산이 필요없는, 즉,
포인터 연산의 실수에 대한 걱정 및 우려가 적은 레퍼런스를 사용하는 것입니다.
예제를 레퍼런스로 바꿔보죠.

/*
swap_ref.cpp
*/
#include
using namespace std;

void swap(int &a,int &b);

int main(){
int x=0,y=1;

cout<
swap(x,y);
cout<

return 0;
}

void swap(int &a,int &b){
int temp=a;
a=b;
b=temp;
}

달라진 부분에만 조금 표기해 보았습니다.
swap함수에서 레퍼런스로 받기 때문에, 메인함수에서도 주소값을 넘겨줄 필요가 없으며,
swap함수에서도 포인터 연산자 '*'를 사용할 필요가 없어,
딱봐도 소스가 훨씬 간결하고 아름다워진 것을 보실수 있으실것입니다.

즉, 레퍼런스를 사용하며 소스의 간결성과 안정성, 두마리 토끼를 잡을수 있습니다.

이상으로 다음강에서 만나죠~




오늘 하루 쫙~ 강좌 나가봅시다!! 

잼군요 하핫;;

 *이 강좌는 C언어를 끝냈다는 가정하에 실시합니다.

┌───────────────┐
---앞으로의 목차---
2-2. Reference란.
2-3. 레퍼런스와 함수
2-4. 레퍼런스의 이용
└───────────────┘

<지난 강좌를 살펴보고 와주세요 !! : http://blog.naver.com/owndks98o/120155831162 >

2-2. Reference란.
레퍼런스가 무엇일까요?
이해를 돕기위해 간단한 예를 들어 이야기해 봅시다.

우리는 사람을 부를때에 이름으로 부르기도 하지만, 그 사람의 별명을 가지고 그 사람을 이야기 하기도 합니다.

즉, 여기서의 "이름"과 "별명"에 대해
"이름"=="별명"
이 성립하는 것이죠.

이것이 레퍼런스 입니다.
이미 존재하는 변수에 별명을 부여해 주는 것이죠.

레퍼런스를 선언하는 방법, 즉 별명을 붙이는 방법은 간단합니다.
int형 val이라는 변수가 있을때에,
int &ref=val;
의 한줄로써 별명을 만들수 있습니다.

?? 한가지 이해가 안가는 부분이 있군요.
'&'
연산자는 C의 포인터에서도 사용하였습니다.
그러고 보니 레퍼런스가 포인터와 비슷한거 같기도 하고요.
(하지만 포인터는 "주소값"을, 레퍼런스는 "변수 제2명"에 대해 다릅니다.)

하지만 아래의 예제를 보면 분명 다르다는 것을 알수 있습니다.

int main(){
int val=0;

int *ptr=&val;   //주소값 얻어오기
int &ref=val;    //레퍼런스 선언

return 0;
}

어때요? 다르죠? 하핫;;

레퍼런스를 선언할때에는 단 1가지 규칙만이 필요합니다.
  • 변수명을 대입하여 초기화 하여야 한다.
간단하죠?

따라서, 요약하면,
레퍼런스는 하나의 메모리 공간에 2개 이상의 이름을 붙여주는 것
입니다.

레퍼런스는 포인터 연산에 유리하다는 듯, 여러가지 장점이 있습니다.
적어도 포인터 연산을 잘못해서 에러가 나는 일은 없으니까요.

이상으로 다음강에서 뵙겠습니다!




살며시.. 하루정도 쉬고 왔습니다 하핫;; 

그럼 C++ 의 엄~청난 기능을 가진 새로운 자료형인 bool을 알아봅시다!

*이 강좌는 C언어를 끝냈다는 가정하에 실시합니다.

┌───────────────┐
---앞으로의 목차---
2-1. bool형에 대해
2-2. Reference란.
2-3. 레퍼런스와 함수
└───────────────┘

<지난 강좌를 살펴보고 와주세요 !! : http://blog.naver.com/owndks98o/120155697631 >

2-1. bool형에 대해
C++에서는 bool이라는 자료형이 추가되었습니다.
bool은 논리형으로써, true와 false만을 값으로 가집니다.
C에서는 매크로를 이용하여, true와 false를 정의하였지만,
C++에서는 더욱 업그레이드 된 방식으로 C++자체에서 키워드로 제공하게 됩니다.

/*
boolExample.cpp
*/
#include
using namespace std;

int main(){
bool Open=false;
for(;;){
cout<<"현재 문의 상태 : ";
if(Open)
cout<<"<열려있음>"<
else(!Open)
cout<<"<닫혀있음>"<

Open=!Open;
}
return 0;
}

프로그램을 실행하시면 열려있음/닫혀있음 이 토글되며 출력될 것입니다.

그리고 C를 배울때에, 0이면 거짓, 0이 아니면 진실 이었습니다.
그렇다면 if문에도 적용되는 것을 보니, bool형의 두 값은 0과 다른 한 숫자로 이루어져 있는 것일까요?

/*
boolExample2.cpp
*/
#include
using namespace std;

int main(){
int BOOL=true;
cout<<"TRUE : "<

BOOL=false;
cout<<"FALSE : "<

return 0;
}

이 프로그램을 실행해 보시면,
true는 1, false는 0 으로 되어있는 것을 알수 있을 것입니다.

최근표준에는 C에도 bool,true,false가 추가되었지만 아직은 배포에 시간이 걸릴것 같습니다 :D
bool형의 쓰임은 지금당장은 이해하기 쉽지 않으실 거라 생각됩니다.
C++을 하다보면 꼭 여러본 보게 될 테이니 서서히 익혀 지실거라 판단합니다 :D


+ Recent posts