1. 멤버이니셜라이저란?
멤버이니셜라이저 (변수초기화방식) : 선언과 동시에 초기화한다.
함수 : 초기화 할 변수(초기화 될 값)
형식으로 선언해준다.
예시로 const 변수와 함께 멤버이니셜라이저를 살펴보자.
//const 변수는 반드시 선언 시 초기화를 해야 한다. 즉, 초기화하지 않으면
//컴파일 에러가 발생한다. 따라서 class나 struct의 멤버변수를 const로 선언 시에는
//반드시 초기화 히스트(initialize list)를 사용해야 한다.
//정상적인 코드
class ConstExample{
const int num;
ConstExample(void) : num(3); //이것이 멤버이니셜라이저이다.
};
//컴파일 에러가 나는 코드
class ConstExample{
const int num;
ConstExample(void){
num = 3; //컴파일 에러 발생
}
};
2. 생성자와 소멸자를 이용한 동적할당 -> 생성자와 멤버이니셜라이저 동시 사용!
아래 코드 주석을 보면 생성자를 이용하여 어떻게 동적할당을 하고,
소멸자를 이용하여 메모리 반환을 하는지 잘 알 수 있다.
#include <iostream>
using namespace std;
class nameCard {
//변수는 private으로 지정
string *person_name, *company_name, *phone_number;
//성명, 회사 이름, 전화번호 //동적할당은 포인터 선언을 해줘야 함.
public: //생성자와 소멸자는 public으로 지정
void ShowNameCardInfo();
//함수는 메인함수에서 인자를 받아야하므로 private으로 선언하면 오류남.
nameCard(string person_name, string company_name, string phone_number);
//생성자도 하나의 함수이므로 매개변수 써줘야 함.
~nameCard(); //소멸자
};
nameCard::nameCard(string person_name, string company_name, string phone_number)
:person_name(new string(person_name)), company_name(new string(company_name)),
phone_number(new string(phone_number))
//멤버이니셜라이저 사용
{ //동적할당하는 생성자
/*string* person_name = new string;
string* company_name = new string;
string* phone_number = new string;*/
// -> 이렇게 하면 안 됨. NameCard에 이미 선언된 거를 또 선언해주는 꼴..
//멤버이니셜라이저 사용하면 this 사용 안해도 됨, 멤버이니셜라이저는 함수 내에서 선언x 함수 밖에서
}
nameCard::~nameCard() { //동적할당을 해제하는 소멸자
delete person_name;
delete company_name;
delete phone_number;
}
void nameCard::ShowNameCardInfo(){
cout << "이름 : "<<*(this->person_name) <<'\n';
//person_name이 포인터 변수이므로 this ->임. 그냥 변수일 때는 마침표쓰면 됨.
cout << "회사 : " << *company_name << '\n';
//애스터리스크 안 쓰면 company_name의 주소값이 나옴
cout << "전화번호 : " << *phone_number << '\n';
}
int main(void) {
nameCard manClerk("Lee", "ABCEng", "010-1111-2222");
nameCard manAsist("Hong", "OrangeEng", "010-3333-4444");
nameCard manSENIOR("Kim", "soGoodComp", "010-5555-6666");
manClerk.ShowNameCardInfo();
cout << '\n';
manAsist.ShowNameCardInfo();
cout << '\n';
manSENIOR.ShowNameCardInfo();
return 0;
}
위 코드에서
nameCard::nameCard(string person_name, string company_name, string phone_number)
:person_name(new string(person_name)), company_name(new string(company_name)),
phone_number(new string(phone_number))
//멤버이니셜라이저 사용
{ //동적할당하는 생성자
/*string* person_name = new string;
string* company_name = new string;
string* phone_number = new string;*/
// -> 이렇게 하면 안 됨. NameCard에 이미 선언된 거를 또 선언해주는 꼴..
//멤버이니셜라이저 사용하면 this 사용 안해도 됨, 멤버이니셜라이저는 함수 내에서 선언x 함수 밖에서
}
이 부분을 보자.
만약 여기서 멤버이니셜라이저를 사용하지 않는다면 어떻게 될까?
아래 코드와 같이 this를 사용하면 된다.
//this 사용
nameCard::nameCard(string person_name, string company_name, string phone_number)
{
this->person_name =new string(person_name);
this->company_name =new string(company_name);
this->phone_number =new string(phone_number);
}
3. 여기서 this가 가리키는 변수는 무슨 변수일까? ->멤버볌수를 가르킨다.
NameCard::NameCard(const char* name, const char* company, const char* phone) 안에 있는 매개변수 가리키는 거 아님!
NameCard::NameCard(const char* name, const char* company, const char* phone) { // 생성자
this->name = new char[strlen(name) + 1]; // name 길이만큼 동적할당, +1은 null문자 자리// 1 추가 안해주면 메모리 오류 남
strcpy(this->name, name);
this->company = new char[strlen(company) + 1]; // company 길이만큼 동적할당, +1은 null문자 자리
strcpy(this->company, company);
this->phone = new char[strlen(phone) + 1]; // phone 길이만큼 동적할당, +1은 null문자 자리
strcpy(this->phone, phone);
}
참고로
this->name = new char[strlen(name) + 1]; 은
(*this).name = new char[strlen(name) + 1]; 과 똑같다..!
아래는 전체코드이다.
#include <iostream>
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)
using namespace std;
class NameCard // NameCard 클래스 생성
{
private: // 멤버 변수 선언
char* name;
char* company;
char* phone;
public:
// const 안붙이면 오류 나는데 이유를 모르겠다..
NameCard(const char* name, const char* company, const char* phone); // 생성자
~NameCard(); // 소멸자
void ShowNameCardInfo(); // 입력한 NameCard정보 출력하는 함수
};
NameCard::NameCard(const char* name, const char* company, const char* phone) { // 생성자
this->name = new char[strlen(name) + 1]; // name 길이만큼 동적할당, +1은 null문자 자리
// 1 추가 안해주면 메모리 오류 남
strcpy(this->name, name);
this->company = new char[strlen(company) + 1]; // company 길이만큼 동적할당, +1은 null문자 자리
strcpy(this->company, company);
this->phone = new char[strlen(phone) + 1]; // phone 길이만큼 동적할당, +1은 null문자 자리
strcpy(this->phone, phone);
}
NameCard::~NameCard() { // 소멸자
delete[]name; // 동적할당 받은 메모리 반환
delete[]company;
delete[]phone;
}
void NameCard::ShowNameCardInfo() { // 입력한 정보 출력
cout << "이름 : " << name << endl;
cout << "회사 : " << company << endl;
cout << "전화번호 : " << phone << endl;
cout << endl;
}
int main()
{
NameCard manClerk("Lee", "ABCEng", "010-1111-2222");
NameCard manAssist("Hong", "OrangeEng", "010-3333-4444");
NameCard manSENIOR("KIM", "SoGoodComp", "010-5555-6666");
manClerk.ShowNameCardInfo();
manAssist.ShowNameCardInfo();
manSENIOR.ShowNameCardInfo();
return 0;
}
'언어 > C++' 카테고리의 다른 글
[C++] locale이란? (0) | 2023.09.29 |
---|---|
[C++] 얕은 복사, 깊은 복사 (0) | 2023.09.25 |
[C++] 참조자가 객체로 쓰였을 때는? (0) | 2023.09.25 |
[C++] *this가 반환 값일 때, 함수의 반환형에 &를 쓰는 이유 (+ this와 *this의 차이) (0) | 2023.09.24 |
[C++] 동적 할당(dynamic allocation) (0) | 2023.09.21 |