자료실/C++

C++ - 클래스(class) 생성자와 소멸자

자료수집중 2020. 8. 19.
반응형

 

이번에는 클래스의 생성자와 소멸자에 대해 알아보겠습니다.

 

생성자는 객체가 선언될 때 자동으로 호출이 되는 특수한 멤버 함수입니다.

보통 생성자를 이용해서 객체가 선언될 때 객체를 초기화를 할 수 있습니다.

클래스 이름과 동일한 함수명을 가지고 있습니다.

생성자는 특수한 함수답게 반환값이 없습니다. 반환값이 없다 보니 자료형을 붙이지 않고 정의합니다.

예제를 통해서 알아보겠습니다.

#include <iostream> 

using namespace std; 

class Student { 
    public:
        Student() //생성자
        {
            cout << "객체 생성 \n";
        }
	

};

int main() 
{ 
    Student str;

    return 0; 
}

기본적으로 생성자는 객체가 생성되면 자동으로 호출되는 결과를 볼 수 있습니다.

main함수에서 아무 메서드도 호출하지 않았지만 자동으로 생성자가 호출되어 내부의 명령이 실행됩니다.

 

생성자의 다른 사용법도 알아보겠습니다.만약 클래스 내부에 변수를 초기화하지 않고 호출하면 어떤 결과가 나오는지 알아보겠습니다.

#include <iostream> 

using namespace std; 

class Student { 
private:
	int age;
public:
	void show() {
		cout << age << '\n';
	}

};

int main() 
{ 
	Student str;
	str.show();
	return 0; 
}

초기화되지 않은 변수를 사용하여 쓰레기 값이 출력됩니다.

private으로 접근 지정자를 선언해서 외부에서 초기화도 불가능합니다.

한두개의 변수야 직접 초기화도 가능하지만 양이 많아지게 되면 하나하나 초기화하려면 굉장히 번거로운 작업이 될 수 있습니다.

이때 생성자를 이용하여 한번에 0으로 초기화가 가능합니다.

다시 예제를 수정해보겠습니다.

#include <iostream> 

using namespace std; 

class Student { 
private:
	int age;
public:
	void show() {
		cout << age << '\n';
	}

};

int main() 
{ 
	Student str{};
	str.show();
	return 0; 
}

객체를 생성할때 빈 {}중괄호를 붙여주면 초기화되지않은 변수들이 모두 0으로 (문자는 \0) 초기화됩니다.

단 이때 클래스 내부에 생성자를 정의하지 않은 상태이거나(기본 생성자)  매개변수를 갖지 않은 기본 생성자를 직접 정의해야 합니다.

{}는 균일한 초기화(Uniform initialization)라고 해서 ()나 =와는 조금 다른 개념입니다.(C++ 11부터 추가)

빈 중괄호는 기본 초기화로 변수를 모두 0으로 초기화해줍니다.

 

 

 

 

생성자는 매개변수를 가질 수 있습니다.

예제를 통해서 생성자에 매개변수를 추가해보겠습니다.

#include <iostream> 
#include <string>

using namespace std; 

class Student { 
private:
	string name;
	int age;
public:
	Student(string name,int age) {
		this->name = name;
		this->age = age;
	}
	void show() {
		cout << "이름 : " << name << '\n';
		cout << "나이 : " << age << '\n';
	}

};

int main() 
{ 
	Student str("홍길동",16);
	str.show();
	return 0; 
}

매개변수를 가지는 생성자를 만들게 되면 객체를 선언할 때 인자를 넘겨주지 않으면 에러가 발생합니다.

생성자에서 this는 this 포인터로 객체 자신을 가리키는 포인터입니다.

this와 ->(포인터 연산자)를 이용해서 자신의 클래스 내부의 변수 또는 함수를 사용할 수 있습니다. 위의 예제처럼 매개변수의 이름이 클래스 내부 변수 이름과 같을 때 구분용으로 많이 사용하기도 합니다.

 

다음으로 생성자는 여러 개 선언이 가능합니다.

위의 예제를 예로 들었을 때 학생의 이름은 알지만 나이를 모를 수도 있고 일단 객체만 생성하고 싶을 수도 있습니다.

다시 예제를 수정해보겠습니다.

#include <iostream> 
#include <string>

using namespace std; 

class Student { 
private:
	string name;
	int age;
public:
	Student() {
		cout << "객체 생성 \n\n";
	}
	Student(string name) {
		this->name = name;
		this->age = 0;
		show();
	}
	Student(string name,int age) {
		this->name = name;
		this->age = age;
		show();
	}
	void show() {
		cout << "이름 : " << name << '\n';
		cout << "나이 : " << age << '\n';
	}

};

int main() 
{ 
	Student str1;
	Student str2{"홍길동"};
	Student str3("홍길동",16);

	return 0; 
}

각각 객체를 생성할 때 원하는 생성자의 매개변수에 맞게 인자를 넘기면 해당 생성자가 호출됩니다.

 

여기서 {}(중괄호)로 매개변수를 가진 생성자를 초기화할 때 주의해야할 점이 있습니다.

균일한 초기화는 형 변환을 허용하지 않습니다.

예를 들어 int형의 매개변수를 가지는 생성자가 있는 경우

class Student { 
private:
	int age;
public:
	Student(int age) {
		this->age = age;
	}
};

()괄호로 초기화할 때는 실수형을 넘겨도 자료 손실이 있다는 주의 메시지만 출력되고 정상적으로 실행되고

내림 후 변수에 저장됩니다.

Student str1( 3.5 );

하지만 {}중괄호는 에러가 발생합니다.

Student str2{ 3.5 };

균일한 초기화는 형 변환을 허락하지 않기 때문입니다.

 

 

 

이제 소멸자에 대해 알아보겠습니다.

소멸자는 객체가 소멸할 때 자동으로 호출되는 함수입니다.

소멸자도 클래스명과 같은 이름입니다 대신 생성자와 구분하기 위해 이름 앞에 ~가 붙습니다.

소멸자도 기본적으로 호출되기 때문에 따로 선언할 필요는 없습니다.

#include <iostream> 
#include <string>

using namespace std; 

class Student { 
public:
	~Student() {
		cout << "객체 소멸 \n";
	}
};

int main() 
{ 
	Student *str1 = new Student;
	
	delete str1;

	return 0; 
}

여기서 new는 동적 할당을 위한 연산자로 나중에 따로 하겠습니다.

new로 생성된 객체 포인터를 delete로 소멸시키자 자동으로 소멸자가 호출되어 메시지가 출력됩니다.

 

'자료실 > C++' 카테고리의 다른 글

C++ - 동적 메모리 할당  (0) 2020.08.25
C++ - 클래스(class) 상속  (0) 2020.08.21
C++ - string 클래스  (0) 2020.08.18
C++ - 클래스(Class)의 구조와 접근 지정자  (0) 2020.08.17
C++ - 네임스페이스(namespace)  (0) 2020.08.13

댓글