일반 변수와 마찬가지로 어떤 함수 내에서 생성된 인스턴스는 지역 인스턴스, 함수 바깥에 선언된 인스턴스는 전역 인스턴스이다. 전역 인스턴스는 프로그램이 실행될 때 생성되고 프로그램이 종료될 때 소멸된다. 그리고 지역 인스턴스는 함수가 실행될 때 생성되고 함수가 종료될 때 소멸된다.


 다음 예를 가지고 생성자와 소멸자의 실행 순서를 설명하도록 하겠다. 여기에서 rect1 은 함수 바깥에서 생성된 전역 인스턴스이고 rect2, rect3 는 함수 func()의 지역 인스턴스이다.

class Rect {
   .....
};
Rect rect1;
void func() {
   Rect rect2;
   Rect rect3;
   .....
}
int main() {
   .....
   func();
   .....
}

위 예제와 같이 main()함수에서 func() 함수가 호출될 때 rect2, rect3 의 순으로 인스턴스가 생성되며 생성자도 같은 순서로 호출된다. 하지만 func() 함수가 종료될 때는 그 역순으로 소멸되며 소멸자도 역순으로 호출된다.


 전체적인 생성자와 소멸자의 호출순서를 좀 더 자세히 기술하면 다음과 같다.



프로그램 시작

   rect1 객체 생성 (생성자 호출)

   main()함수 실행
       .....

       func()함수 실행
       rect2 객체 생성 (생성자 호출)
       rect3 객체 생성 (생성자 호출)
       .....
       rect3 객체 소멸 (소멸자 호출)
       rect2 객체 소멸 (소멸자 호출)
       func()함수 종료

       .....
   main함수 종료

   rect1 객체 소멸 (소멸자 호출)

프로그램 종료

전역 인스턴스는 전역 변수와 마찬가지로 그 밑에 위치한 모든 함수에서 접근할 수 있는 반변 지역 인스턴스는 포함된 함수 내부에서만 접근할 수 있고 함수의 실행이 끝나면 소멸된다.


C++ 강좌 전체 목록 >>>


c{c++},n{c0022}

Posted by 살레시오
,

 클래스에는 반드시 생성자가 있어야 하며 인스턴스를 생성할 때 반드시 하나의 생성자가 호출되도록 정해져 있다. 사용자가 생성자를 하나도 선언/구현하지 않은 경우에도 컴파일러가 기본 생성자(default constructor)를 만들어서 인스턴스 생성시에 이 기본 생성자를 호출하게 된다. 기본 생성자는 입력 인자가 없는 생성자이다.


 즉, 만약 다음과 같이 생성자가 없다면


class Rect{
   public:
      int width;
      int height;
};


컴파일러는 다음과 같이 입력 인자가 없는 기본 생성자를 자동으로 만들어 준다. 기본 생성자는 inline 멤버 함수로서 아무일도 하지 않는다.


class Rect{
   public:
       int width;
       int height;
       Rect() {}; // 자동으로 생성되는 기본 생성자
};


이와 같이 사용자가 생성자를 하나도 선언/정의하지 않았을 경우 C++ 컴파일러는 백그라운드에서 기본 생성자를 삽입하여 인스턴스 생성 시에 호출한다.


 한 가지 주의할 점은 생성자가 하나라도 선언된 클래스는 기본 생성자가 자동으로 생기지 않는다는 점이다. 이 말은 만약 매개변수가 있는 생성자들만 있는 경우 인스턴스 선언에서 입력 인수가 없이 선언한 경우는 오류를 발생하게 된다는 의미이다. 기본 생성자가 없기 때문이다. 예를 들어서


class Rect {

   public:

       Rect(int iw, int ih);
       int width;
       int height;
};
Rect::Rect(int iw, int ih) { // 입력 인수가 두 개인 생성자
   width = iw;
   height = ih;
}


와 같이 클래스가 정의된 경우에


Rect rect; //에러 발생


라고 인스턴스를 생성하려하면 에러를 발생시킨다. 왜나면 이 경우 기본 생성자를 호출해야 하는데 클래스 정의에서 입력 인수가 두 개인 생성자가 정의되어 있으므로 컴파일러는 자동으로 기본 생성자를 만들지 않기 때문이다. 따라서 없는 기본 생성자를 호출한 격이 되므로 에러를 발생한다.


C++ 강좌 전체 목록 >>>


c{c++},n{c000x}

Posted by 살레시오
,

 생성자(constuctor)란 클래스의 인스턴스가 생성되는 시점에서 자동으로 호출되는 특수한 멤버 함수이다. 생성자 내에서 일반적으로 멤버 변수들을 초기화 시키거나 기타 객체 인스턴스를 생성하는데 필요한 작업들을 수행하게 된다.


class Rect {
   public:
       Rect(); // 생성자1 선언
       int width;
       int height;        
       ....

};
// 생성자 구현
Rect::Rect() { // 입력 인수 없는 생성자
   width = 0;
   height = 0;
}


생성자의 이름은 클래스의 이름과 같다. 생성자는 특별한 경우가 아니면 보통 public 멤버 함수이다. 또한 반환값이 없으며 그럼에도 불구하고 void 를 붙이지 않는다는 점에 주의해야 한다. 이렇게 생성자 있다면 다음과 같이 객체를 생성하는 시점에서


Rect rect1;


입력 인자가 없는 생성자가 호출되어 객체 생성에 필요한 작업을 수행하게 된다.


 생성자는 여러 개를 정의할 수 있으나 (constructor overloading) 이들 중 하나만 실행된다. 아래는 생성자가 두 개인 경우의 예이다.


class Rect {
   public:
       Rect(); // 생성자1 선언
       Rect(int iw, int ih); //생성자2 선언
       int width;
       int height;        
       ....

};
// 생성자 구현
Rect::Rect() { // 입력 인수 없는 생성자
   width = 0;
   height = 0;
}

Rect::Rect(int iw, int ih) { // 입력 인수가 두 개인 생성자
   width = iw;
   height = ih;
}


 

 생성자는 반환값이 없기 때문에 어떤 값도 return해서는 안되지만 중간에 실행을 멈추기 위해서 반환값이 없는 단순 return문은 사용할 수 있다. 만약 다음과 같이 생성자를 입력한다면 오류를 발생시킬 것이다.


Rect::Rect() {
   width = 0;
   height = 0;
   return 0; // 오류 발생

}


그리고 생성자는 여러 개를 중복하여 선언하고 구현할 수 있으나 각각의 입력 인수의 개수나 타입이 서로 달라서 구별되어야 한다. 즉, 이 경우 C++의 일반적인 함수 중복의 규칙에 따른다. 따라서 예를 들어 다음과 같이 여러 개의 생성자를 선언할 수 있다.


Rect();
Rect(int x);
Rect(double y);
Rect(int x, int y);


위에서 든 네 개의 생성자는 서로 입력 인수가 다르므로 다른 생성자이다. 단, 인스턴스 생성시에는 이 중 단 하나만 실행된다.


 생성자에게 입력 인자를 넘기려면 인스턴스 바로 뒤에 괄호로 묶어서 넘기면 된다.


Rect rect1; // 입력 인수가 없는 생성자 호출
Rect rect2(10,20); // 입력 인수가 두 개인 생성자 호출


이렇게 마치 함수를 호출하듯 객체명 뒤에 인자를 주면 입력 인자가 매치가 되는 생성자가 호출되게 된다. 즉, rect1이 생성될 때 Rect() 생성자가 호출되고 rect2가 생성될 경우에는 Rect(int iw, int ih) 생성자가 호출된다. 따라서 rect1의 내부 변수들은 모두 0으로 초기화 되어 있게 되고 rect2의 내부변수는 각각 10과 20으로 초기화가 되었다.


rect1.getArea(); // 0을 반환
rect2.getArea(); // 20을 반환


C++ 강좌 전체 목록 >>>


c{c++},n{c0019}


Posted by 살레시오
,