언어/기타
2005.05.26 08:15

[c++] 생성자,파괴자

조회 수 1628 추천 수 7 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
생성자, 파괴자

가. 생성자


클래스의 선언에 의해 클래스형을 컴파일러에게 알리고 instance를 생성함으
로써 클래스가 구현되고 이후부터 클래스형의 object를 사용할 수 있다. 그런
데 예제 18-4의 main 함수에서 instance 생성 후의 동작을 보자.

HERE.px = 10;
HERE.py = 10;
HERE.ch = 'S';
HERE.outpos();

object내의 데이터 멤버에 어떠한 값을 정의해준 후 멤버 함수를 호출하고 있
다. object 내의 데이터 멤버는 어떤 값을 담고자 준비된 것이므로 값이 대입
되지 않고서는 사용한다는 것 자체가 무의미해진다. 그래서 instance 생성 직
후에 의미있는 어떤 값을 대입해 주었으며 이 과정은 너무나 당연하고 instance
생성 후에 필연적으로 이어지는 과정이다. 그래서 어차피 instance 생성 후에
데이터 멤버에 어떤 값을 줘야 한다면 instance 생성과 데이터 멤버에 값을 부
여하는 과정을 한번에 통합해 버린다고 하더라도 문제될 것은 없으며 여러 면
에서 편리해질 것이다.
instance를 생성하는 과정은 메모리상에 클래스가 가진 데이터 멤버가 들어갈
자리를 확보하기는 하지만 데이터를 초기화하지는 않고 원래 메모리에 들어 있
던 값, 즉 쓰레기값을 그대로 유지한다. int k; 하면 정수형 변수 k가 들어갈
메모리 2바이트를 할당은 하지만 초기화는 하지 않는다는 것을 연상하면 쉽게
이해가 갈 것이다. 선언과 동시에 초기화를 하고자 한다면 int k = 3; 등으로
해야 한다.
클래스의 경우에도 초기화의 문제는 여전히 여타의 다른 데이터 타입과 마찬
가지로 세심하게 신경을 써 주어야 한다. 클래스보다 크기가 작은 여타의 다른
데이터 타입(정수, 실수, 문자형 등등)은 대입(잘 알겠지만 int k = 3; 등에
쓰인 '='은 대입 연산자가 아니다. 다만 초기화식에 사용된 구두점일 뿐이다.)
에 의해 이러한 초기화를 해결하지만 여러 가지 데이터 멤버와 복잡한 구조를
가진 클래스는 대입과 같은 간단한 방법으로는 초기화를 하기가 곤란하기 때문
에 초기화를 전문적으로 해주는 함수가 필요하다. instance를 초기화시켜 주는
특별한 멤버 함수가 있는데 이 멤버 함수를 생성자(constructor)라고 한다.
생성자는 일반적인 함수와는 다른 특징들이 많이 있지만 그 중에서도 표면상
드러나는 가장 큰 차이는 클래스의 이름과 동일한 이름을 사용한다는 것이다.
생성자는 객체가 만들어질 때 자동으로 호출되며 객체를 초기화시키는 것이 주
임무이다. 하나의 instance가 생성되는 과정은 다음과 같다.

┌──────┐ ┌─────┐ ┌─────┐
│ │ │ │ │ │
│ class 선언 ├────┤인스턴스 ├────┤ 생성자 │
│ │ /│ 생성 │ /│ 호출 │
└──────┘ └─────┘ └─────┘
class형의 데이터형을 메모리상에 구현 데이터 멤버의
컴파일러에게 알림 초기화

일단 생성자를 사용한 예제를 보자.

#include
#include
#include

class Position
{

public:
int px;
int py;
char ch;
void outpos();
Position( int, int, char); // 생성자 함수
};

void Position::outpos()
{
gotoxy( px, py);
putch( ch);
}

Position::Position( int x, int y, char c) // 생성자 함수의 정의
{
px = x; // data member를 초기화시킨다.
py = y;
ch = c;
}

void main()
{
clrscr();
Position HERE( 10, 10, 'S'); // 객체의 생성과 동시에 초기화
HERE.outpos();
}

클래스 이름이 Position이므로 생성자는 당연히 Position()이 된다. 생성자 Po
sition()은 세 개의 인수를 받아 데이터 멤버 px,py,ch에 각각 대입을 해주는
간단한 구조로 되어 있다. 생성자는 객체가 생성될 때 특별히 호출하지 않아도
자동으로 호출된다. 즉 메모리가 할당되고 난 직후에 생성자가 호출되어져 할
당받은 메모리를 초기화시키게 된다.
Position HERE;가 객체가 생성되는 시기이므로 이 문장을 실행할 때 생성자가
호출된다. 그런데 생성자도 분명히 함수이므로 인수를 요구하며 어떤 형태로든
지 인수가 함수로 전달되어야 한다. 일거리를 안주고 어떻게 일을 시키겠는가
말이다. 그래서 객체를 선언하는 문장에 생성자의 인수가 나타나게 되며 Posit
ion HERE(10, 10, 'S')와 같은 식으로 된다.
Position형의 object HERE를 생성하되 그 생성자의 인수를 (10,10,'S')로 한
다는 선언문이다. 생성자에 의해 object 선언과 동시에 객체의 데이터 멤버를
초기화시킬 수 있게 되었으므로 이제 프로그래밍이 훨씬 더 간단해지게 되었다.
예제를 보면 알겠지만 main 함수가 단 세 줄로 끝이 났다. 생성자는 여러개 동
시에 존재할 수가 있다. 함수가 다형성에 의해 인수가 다르면 동일명으로 여러
개가 있을 수 있듯이 생성자도 함수이므로 인수만 다르다면 여러개가 있어도
상관없다. 위 예제에 다음과 같은 생성자를 하나 더 추가시켜 보자. 물론 클래
스 정의 블럭 안에 원형도 밝혀 주어야 한다.

Position::Position(int xy,char c)
{
px=py=xy;
ch=c;
}

데이터 멤버 px,py를 같은 값으로 정의하는 생성자이므로 생성되는 객체는 대
각선상의 위치만을 나타내게 된다. 두 개의 생성자가 동시에 존재하므로 다음
두 선언은 동일한 모양의 객체를 만들지만 초기값이 다른 객체가 만들어지며
그 이유는 객체 생성시 호출되는 생성자가 다름에 기인한다.

Position A(10,18,'D');
Position B(16,'S');

컴파일러는 객체가 생성될 때 객체 이름 뒤의 생성자로 전달된 인수들을 보고
적절한 생성자를 자동으로 호출해준다. 만약 이 상태에서 Position C(1,2,"str
ing");이라는 생성자를 호출하면 어떻게 되겠는가? 이런 경우는 컴파일러가 대
응되는 적절한 생성자를 찾을 수 없기 때문에 에러로 처리된다. 생성자 함수에
디폴트 인수가 적용되는 경우도 비교적 빈번하게 발생한다. 다음의 생성자는
세 번째 인수가 전달되지 않을 경우 'S'를 세 번째 인수로 취하는 생성자 함수
이다.

Position::Position(int x,int y,char c='S') // default 인수
{
px=x;
py=y;
ch=c;
}

생성자 함수가 정의되어 있지 않을 경우는 아무런 초기화도 이루어지지 않으며
에러는 발생하지 않는다. 초기화가 굳이 불필요하거나 아니면 초기화를 해주는
별도의 멤버 함수를 사용할 수도 있기 때문이다. 생성자의 사용에 또 한 가지
주의할 것은 다음과 같이 인수를 취하지 않는 생성자도 있을 수 있다.

Position::Position() // 인수가 없음
{
px=random(80);
py=random(25);
ch=random(80)+20;
}

인수가 없는 생성자도 객체 생성시에 호출되기는 마찬가지이지만 객체 선언문
에 다음과 같이 생성자 호출을 위한 괄호를 붙여서는 안된다.

Position D();

일반 함수는 인수가 없더라도 함수임을 나타내기 위해 빈 괄호를 써 주어야 하
지만 생성자는 자동으로 호출되는 것이기 때문에 인수가 없을 경우는 괄호 조
차도 필요가 없다. 괄호가 있으면 오히려 엉뚱한 에러가 발생하므로 인수 없이
Position D;와 같은 형태로 객체만 생성하면 된다. 생성자 중에는 복사 생성자
(copy constructor)라고 하는 아주 특별난 생성자도 있다. 문법은 간단하다.

Position A=B;

같은 클래스형의 다른 객체의 값을 그대로 복사받는 형태로 객체가 생성된다.
int i=j;와 비슷한 형태의 동작을 하며 여러 개의 객체를 똑같은 값으로 초기
화할 때 아주 편리하게 사용할 수 있는 방법이다. 그러나 복사 생성자는 겉으
로는 간단해 보여도 속으로는 말썽의 소지가 굉장히 많은 생성자이다. 어떤 경
우에 문제가 되는가 하면 객체 내에서 동적으로 메모리를 할당해서 사용할 때
같은 메모리 영역을 두 객체가 동시에 포인트한다는 점이다. 물론 해결책도 있
다.


나. 파괴자

생성자와 반대되는 파괴자(destructor)라는 것도 있다. 클래스에 의해 생성된
object도 변수이므로 생성된 후에 통용 범위를 벗어나면 자동적으로 소멸된다.
생성될 때 다른 변수들과는 달리 특별한 함수를 호출하여 특별한 방법으로 초
기화를 하였으므로 소멸될 때도 일반 변수와는 다른 특별한 방법으로 소멸되어
야 할 경우가 있다. 이때 객체의 소멸을 담당하는 함수를 파괴자라고 한다.
생성자가 클래스의 멤버 함수임과 마찬가지로 파괴자도 클래스의 멤버 함수이
며 이름은 클래스 이름 앞에 '~'를 붙인 것이 된다. 즉 Position 클래스의 파
괴자는 ~Position()이다. 생성자가 객체가 생성될 때 자동으로 호출됨과 마찬
가지로 파괴자는 객체가 통용 범위를 벗어나 메모리로부터 추방당할 때 자동으
로 호출된다. 그러나 파괴자는 생성자 만큼이나 빈번하게 사용되지는 않으며
생성자에서 동적으로 메모리를 할당하지 않거나 객체 소멸시 특별한 조치가 필
요없다면 없어도 무관하다. 파괴자가 꼭 필요한 경우를 보자. 다음 예제에 파
괴자의 기본적인 모양을 보였다.

#include
#include
#include
class Str {
private:
char *name;
public:
Str(char *); // 생성자
~Str(); // 파괴자
void outstr()
{ cout << name << 'n'; }
};
Str::Str(char *initstr) // 생성자에서 메모리를 동적으로 할당
{
name= new char[strlen(initstr)+1];
strcpy(name,initstr);
}
Str::~Str() // 파괴자에서 할당된 메모리를 해제
{
delete name;
}
void main()
{
Str you("Han Sung An");
clrscr();
you.outstr();
} // 여기서 객체 you가 소멸되며 파괴자 호출

이 예제에서 사용하는 클래스 Str은 문자열 포인터 하나만을 데이터 멤버로
가지며 생성자, 파괴자 그리고 문자열을 출력하는 outstr을 멤버 함수로 가지
고 있다. 우선 클래스의 전체 크기가 2바이트임을 이해하자. 클래스의 크기는
데이터 멤버들의 크기의 합이므로 포인터 변수 하나의 크기인 2바이트가 Str클
래스의 크기가 된다. 직접 cout << sizeof(Str);을 해보면 알 수 있다. 물론 L
arge 모델이라면 당연히 4바이트가 될 것이지만 말이다. 클래스 Str은 사람의
이름을 기억하고 출력할 목적으로 만들어졌다.
사람의 이름을 기억하기 위해서는 문자 배열을 사용하는 방법과 문자형 포인
터를 사용하는 방법이 있는데 여기서는 꼭 필요한 만큼만 메모리를 사용하기
위해 문자형 포인터를 사용한다. 실제의 문자열은 메모리의 어딘가에 할당을
해서 저장하고 객체는 그 메모리의 번지만을 가지고 있는 방법이다. 실제 문자
열이 객체 내에 존재하는 것은 아니다. 그래서 객체가 만들어질 때 생성자에서
문자열을 담을 메모리를 new 연산자를 사용해서 동적으로 할당받는다. 할당을
받는 메모리의 크기는 인수로 전해진 초기화 문자열의 크기보다 하나 더 커야
한다(strlen(initstr)+1). 왜냐하면 주어진 문자열 외에도 null 문자를 포함해
야 하기 때문이다.
이렇게 할당한 메모리 번지를 문자 포인터형 데이터 멤버인 name에게 주고 그
번지에 인수로 전해진 초기화 문자열을 복사하면 될 것이다. 여기까지의 메모
리 모양은 다음과 같다.

you 객체
┌───┐
│ ├─────┐
└───┘ │
│/ new 연산자가 동적으로 할당해준 메모리
───────
HAN SUNG AN
───────

"Han Sung An"이라는 문자열이 저장된 메모리 공간은 new 연산자에 의해 동적
으로 할당된 메모리이며 실제 그 번지가 어디인지는 알 수 없으나 어쨌든 그
번지를 Str 클래스의 데이터 멤버인 name이 갖게 된다. 이때 동적으로 할당된
메모리는 you 객체와 물리적으로 연관이 없으며 다만 you 객체의 멤버인 name
에 의해 포인트되는 논리적 관계가 있을 뿐이다. 할당된 메모리는 객체 외부
에 별도로 존재하는 것이다.

main 함수를 보자. 먼저 Str형의 객체 you를 생성하고 생성자가 호출되어 데
이터 멤버 neme이 초기화 문자열 "Han Sung An"으로(정확하게는 그 번지로) 초
기화된다. 이때 생성자 내에서 메모리의 동적 할당이 발생했다. 그리고 화면을
지우고 난 후에 멤버 함수 outstr을 호출해서 문자열을 출력했다. main 함수가
끝나는 시점에서 main 함수 내부의 지역 변수인 you 객체는 통용 범위를 벗어
나게 되므로 메모리에서 삭제(파괴)된다.
객체의 삭제란 객체가 점유하고 있던 메모리를 다시 자유 메모리로 돌리는 것
을 말한다. 그래서 you 객체가 차지하고 있던 2바이트가 메모리로부터(지역 변
수니까 stack) 사라진다. 그러나 이때 문제가 되는 것은 객체는 분명히 없어지
지만 객체에 의해 동적으로 할당되어 있던 메모리는 그대로 할당된 채로 남아
있는다. 왜냐하면 동적으로 할당된 메모리는 객체에 소속되어 있지 않기 때문
에 객체 삭제시 같이 삭제되지 않는다. new나 malloc등에 의해 동적으로 할당
된 메모리는 반드시 delete나 free에 의해 능동적으로 할당이 해제되어야 함을
상기하자.
이러한 문제를 해결하기 위해 C++에서는 객체가 삭제되기 직전에 반드시 파괴
자라고 불리는 특별한 함수를 호출하여 객체 자신이 할당한 메모리를 책임지고
할당 해제할 기회를 준다. 이것이 바로 파괴자(destructor)의 개념이다.
객체 Str의 파괴자 ~Str()은 delete name;이라는 할당 해제를 하도록 정의되어
있다. 객체가 통용 범위를 벗어날 때 객체 자체가 삭제됨은 물론 객체가 할당
한 메모리도 파괴자에 의해 삭제되므로 객체가 생성되기 전의 상태로 원상 복
귀가 된다.
파괴자는 주로 이런 동적 메모리 할당 해제에 사용이 되지만 다른 여러 가지
목적으로 사용될 수 있다. 예를 든다면 객체 obj가 특정 텍스트 속성을 사용한
다고 하자. 이때 생성자에서 textattr 함수에 의해 자신이 원하는 속성으로 설
정을 한다면 파괴자에서는 속성을 원위치시켜야 한다. 또한 특정한 그래픽 상
태나, 통신 port의 상태를 원하는 객체에서는 생성자에서 통신 port를 조작하
고 파괴자에서는 다시 원위치시킨다.
일반적으로 생성자는 객체가 동작하기 위한 환경을 설정하고 파괴자는 객체가
사라질 때 다른 객체가 변경된 환경에 영향을 받지 않도록 하기 위해 환경을
원위치시킨다. 여기서 환경이란 메모리, 그래픽 board 기타 등등의 모든 컴퓨
터 구성 요소가 될 수 있지만 주로 메모리, 그중에서도 특히 동적 할당의 대상
이 되는 heap을 말한다.
잠깐 여기서 생성자, 파괴자의 존재 이유에 대해 생각해보자. 왜 필요한가를
안다는 것은 벌써 반 이상을 아는 것이 된다. 클래스가 다른 데이터 타입과 동
등이라고 하는데 다른 데이터 타입에는 없는 생성자, 파괴자가 왜 유독 클래
스에만 필요한가?
그 이유는 클래스가 워낙 변화무쌍하고 사용자에 의해 자유자재로 만들어질
수 있기 때문이다. 사용자의 자유를 보장해주고자 하다보니 초기화 식이 int i
=3; 등으로 간단해지지가 않고 특별한 함수가 필요하게 되어 생성자라는 멤버
함수가 생겨나게 되었다. 또한 생성자를 만들어 놓고 보니 몇 가지 문제가 생
겨 생성자가 벌려놓은 일을 뒤치닥거리 해줄 파괴자라는 것이 필요하게 된 것
이다.

다. 생성자, 파괴자의 특징

생성자와 파괴자의 대충적인 개념과 형태에 관해 공부해보았다. 생성자와 파
괴자는 일반 함수와는 달리 자동으로 호출되고 맡은 일 자체가 특수한 목적을
띤 일이므로 그 성격이 일반 함수와는 다른 점이 많이 있으며 주의해야 할 사
항도 많다. 다음에 설명한 생성자, 파괴자의 특징을 자세히 읽어보고 그 성질
에 관해서 상세히 알아둘 필요가 있다. 다소 복잡해 보이는 내용이기는 하지만
개념만 확실히 깨우치고 있다면 특징들이야 지극히 당연한 것으로 이해될 것이
다. 가벼운 마음으로 읽어보고 고개 한번 끄덕이고 지나가면 된다.

첫째, 이름이 정해져 있다.
앞에서 언급했지만 클래스 KISS가 있을 경우 생성자의 이름은 자동적으로 KIS
S()가 되고 파괴자의 이름은 ~KISS()가 된다. 사용자가 이름을 마음대로 정하
지 못하고 클래스의 이름을 따라가는 이유는 간단하다. 생성자, 파괴자는 사용
자에 의해 능동적으로 호출되는 것이 아니라 시스템에 의해 객체가 생성, 파괴
될 때 자동으로 호출되는 특성이 있다. 이때 시스템이 생성자, 파괴자를 호출
하기 위해서는 생성자, 파괴자의 이름을 알 수 있어야 하는데 이름을 사용자
마음대로 정하도록 내버려 두었다가는 어느 함수가 생성자인지, 파괴자는 어떤
함수인지를 분간해내지 못하는 모호함이 발생해 버린다. 그래서 멍청한 컴파일
러를 위해 생성자와 파괴자의 이름을 클래스의 이름으로부터 찾을 수 있도록
미리정해 놓았다.

둘째, 리턴값이 없다.
리턴값이 없는 이유는 리턴값을 받아줄 대상이 없기 때문이다. 생성자 파괴자
는 생성되고 파괴될 때 정해진 일을 하도록 되어 있는 함수이지 어떤 값을 조
사하거나 계산하는 함수가 아니다. 일반 함수에 비유하자면 void형 함수에 해
당한다. 그러나 void형이라는 형조차 밝힐 필요도 없다(물론 밝혀도 문제는 없
다).
다른 멤버 함수는 리턴하는 데이터 타입이 있지만 생성자 파괴자는 곧바로 함
수의 이름이 나온다. 클래스 KISS의 생성자의 원형을 밝히라고 한다면 KISS(),
또는 KISS(인수형) 등이 되지 void KISS(), int KISS()가 되지는 않는다. 리턴
값이 없으므로 생성자, 파괴자의 본체에서는 return문을 쓸 필요가 없다.

세째, 생성자는 인수가 있다.
생성자는 데이터 멤버의 초기화를 주로 담당한다. 따라서 생성자 호출시에 데
이터 멤버를 어떻게 초기화시킬 것인가에 대해 인수로 알려주어야 한다. 인수
를 전달해주는 방식도 여러 가지가 있으며 인수가 있음으로 해서 다형성이 성
립되고 따라서 생성자는 인수가 다르면 여러 개 존재할 수 있다.
보통 대여섯개의 생성자가 존재하는 클래스가 허다하다. 객체 생성시에 인수
의 개수와 타입을 보고 어떠한 생성자가 호출될 것인가를 결정하여 적당한 생
성자가 호출된다. 객체를 생성할 때는 생성자 함수의 인수를 객체 뒤에 괄호로
묶어 넘겨 주어야 한다.

네째, 파괴자는 인수가 없다.
생성자는 하는 일이 데이터 멤버에 값을 주어 만드는 일을 하므로 어떻게 만
들 것인가가 전달되어야 하고 따라서 인수가 필요하다. 하지만 파괴자는 주로
할당된 것을 지워 객체 생성 전의 원 상태로 만드는 일을 하며 삭제하는 일에
어떻게 삭제할 것인가 라는 방법이 있을 수 없는 관계로 인수가 필요없다. 즉
없애면 그냥 없애는거지 어떻게 없애는가를 가르쳐 줄 필요가 없다는 것이다.
파괴자는 무조건 인수가 없으며 인수가 없는 관계로 다형성이 성립되지 않게
되고 여러 개의 파괴자가 존재할 수 없다. 한 클래스에는 오직 한 개의 파괴자
만 존재할 수 있다. 클래스 KISS의 파괴자는 무조건 ~KISS()여야 한다. ~KISS
(int), ~KISS(int,double) 등의 파괴자는 있을 수 없다.
설사 파괴자에 인수를 줄 수 있다고 해도 줄 방법도 없지 않은가? 생성자는
생성된 객체 다음에 괄호를 열고 인수를 적어 주지만 파괴자는 자동으로 호출
되는 것이기 때문에 인수를 전달할 기회가 없다.

다섯째, 생성자, 파괴자에도 default가 있다.
만약 어떤 클래스에 생성자도 파괴자도 정의되어 있지 않다면 어떻게 될것인
가. 이때는 객체가 생성될 때나 파괴될 때 아무 일도 하지 않게 된다. 생성할
때 특별히 초기화를 할 필요가 없다면 생성자가 없어도 되지만 보통 생성자는
만들어 두어 초기화를 시키는 것이 보편적이다. 파괴할 때 특별히 삭제해야 할
일이 없다면 파괴자가 없어도 되며 파괴자는 정의하지 않는 경우가 있다.
그러나 생성자, 파괴자를 정의하지 않았더라도 객체가 생성될 때는 생성자가
호출되고, 파괴될 때는 파괴자가 호출된다. 이때 호출되는 생성자, 파괴자를
디폴트 생성자, 디폴트 파괴자라고 하며 인수도 취하지 않고 아무 일도 하지
않는 있으나마나한 존재이다.

여섯째, 생성자나 파괴자는 friend도 static도 될 수 없다.
friend 함수, static 함수를 배워보면 알겠지만 전혀 그럴 필요가 없다.

일곱째, 파괴자는 가상 함수로 정의될 수 있다.
그러나 생성자는 절대로 가상 함수로 정의될 수 없다. 파괴자가 가상 함수로
정의되는 이유는 특성 상속을 충분히 활용하기 위해서이다. 이 부분에 대해서
는 상속과 가상 함수에 대해 알아본 후에 다시 언급한다.
?

List of Articles
번호 분류 제목 글쓴이 날짜 조회 수
864 언어/기타 맵배치 이런식으로 하면 되려나요..?'';; file 땅콩아줌마 2006.12.15 1689
863 RPG Maker 시나리오 혹은 캐릭터 설정에 대해서. 한글화마스터 2006.02.24 1685
862 언어/기타 나라의 PHP 초보탈출 - 1편 나라 2005.05.22 1682
861 언어/기타 [DX&C++] 3D를 넘어 2D로! Zeprod 2007.04.18 1675
860 RPG Maker [RPG2000,2003]게이지쉽게 만드는법 사토루 2005.08.12 1674
859 언어/기타 게임 시나리오 쓰기에 앞서 샤르엘 2007.11.09 1668
858 RPG Maker [RPG2000/3 팁] 간편한 이벤트 단축키 하앵 2015.04.06 1656
857 언어/기타 [다크의 4차원 강좌] 제목 설정의 중요성 1 다크아머 2008.05.19 1651
» 언어/기타 [c++] 생성자,파괴자 챔피온 2005.05.26 1628
855 RPG Maker RXP 메뉴/맵 배치/이벤트 설명 『연금술사』 2005.07.23 1619
854 언어/기타 몬스터의 인공지능 재티s 2006.01.17 1618
853 언어/기타 Fruity Loops에서 FX탭 사용방법 (1) Mr^Lee 2005.05.18 1613
852 RPG Maker 포션없다 시스템 비밀소년 2006.07.28 1613
851 RPG Maker 심심해서 생각해본 rpg2000툴로 전략시뮬(실시간) 만들기 감자는칩이다 2006.10.22 1611
850 RPG Maker 게이지바 공식입니다 CC 2005.08.08 1609
849 RPG Maker 프린세스메이커3를 만들어보자!!①.오프닝편 Ress 2006.01.16 1604
848 언어/기타 1. 변수 응용 프로그램 만들기 천영진 2007.02.21 1602
847 RPG Maker 공격패턴의 다양화 사토루 2006.01.29 1600
846 RPG Maker [rpg2k] 바로가기를 이용해 테스트 플레이 실행하기 1 베넘 2012.01.14 1593
845 언어/기타 리젠 가능한 액알 블리쳐 2005.06.05 1591
Board Pagination Prev 1 ... 3 4 5 6 7 8 9 10 11 12 ... 51 Next
/ 51






[개인정보취급방침] | [이용약관] | [제휴문의] | [후원창구] | [인디사이드연혁]

Copyright © 1999 - 2016 INdiSide.com/(주)씨엘쓰리디 All Rights Reserved.
인디사이드 운영자 : 천무(이지선) | kernys(김원배) | 사신지(김병국)