소프트웨어 개발/C

(2) C++ 기본 빠르게 익히기 - 클래스 및 구조체

늘근이 2017. 8. 5. 21:21

구조체는 다음과 같이 씁니다. 출력함수에서의 일관되지 못한점은 미리 양해드립니다.

<구조체 선언>

#include <stdio.h>
#include <iostream>

struct Member {
char id[100];
int age;
int etc;
};

void showState(const Member &member) {
std::cout<<" id : "<<member.id<<endl;
printf(" age : %d \n", member.age);
printf(" etc : %d \n", member.etc);
return;
}

int main() {

// Member member = new Member("id", 20, 100);
Member member = {"my id", 20, 100};
showState(member);

return 0;
}

특이할점은, struct 다음에 선언부가 끝난곳에 semicolon을 찍어야한다는것이며, 처음에 new를 통해서 객체를 생성하는것이 아니라, 그냥 선언되어있는 순서대로 하나씩 값을 넣어준다는 것입니다. 플레이스 홀더와 같은 역할을 하며, 함수같은 경우 구조체 안에 넣고싶으면 냅다 넣던지 아니면 따로 정의해주면 됩니다.

근데, 메서드를 저렇게 외부에 놔두면 하나도 객체지향적이지 않습니다. 일종의 데이터를 들고다니기를 위해서만 쓰는 구조체인데, 이 안에 메서드도 선언이 가능합니다.

new키워드는 자바와 비교를 위해 주석처리된 부분입니다.

아래와 같이 짜봅니다.

#include <stdio.h>
#include <iostream>

struct Member {

char id[100];
int age;
int etc;

void showState() {
std::cout<<" id : "<<id<<endl;
printf(" age : %d \n", age);
printf(" etc : %d \n", etc);
return;
}

};

int main() {

// Member member = new Member("id", 20, 100);
Member member = {"my id", 20, 100};
member.showState();

return 0;
}

이제는, showState() 메서드가 구조체 안으로 쏙 들어왔습니다. 이정도까지 하면 프로그램 짜는데 크게 문제는 없습니다. 그런데 우리가 익숙하던 그건 어딨나요? public.. private.. 접근제어.. 그리고 생성자.. 이를 위해 C++도 클래스가 있습니다. (별로 일관성은 없어 보이네요) struct대신 class라는 키워드로 바꿔치기하면 되는데, 떨어지지 않던 컴파일 에러가 떨어집니다.

03.1.cpp:22: `member' must be initialized by constructor, not by `{...}'
03.1.cpp:10: `void Member::showState()' is private

아까 걱정하던 그 상황, 즉 생성자와 메서드의 접근권한이 없다는 것입니다. 대부분의 언어 트렌드는 getter setter의 피곤함때문에 기본값이 public으로 되어있는경우가 많은데 (자바는 package private) 기본형이 private인가봅니다.

class Member {

public:
void showState();

char id[100];
int age;
int etc;

};

void Member::showState() {
std::cout<<" id : "<<id<<endl;
printf(" age : %d \n", age);
printf(" etc : %d \n", etc);
return;
}


 

이렇게 하면 돌아가는군요. 대학시절때 여기서부터 멘붕에 빠져 과목을 전혀 따라가지 못해 C++에서 비슷한 학점을 맞은 기억이 나는군요! 아니 왜 접근제한자가 뭔지 friend가 뭔지 이상한 개그를 던지던 교수님도 생각납니다.

어쨌든 실무에서는 접근제한자는 결국 이론가가 아닌 이상에는 private / public 두개만 살아남는 경우를 보았으나 C++은 후렌드가 있다는 점이 신나네요.

 

이제, 클래스의 생성자와 소멸자를 보겠습니다.

아니 왜 굳이 만들었는데 소멸자를 왜 또만들어? 마치 게임같군 하던 기억이 나네요.

자, = {} 로 구조체처럼 초기화하는것은 이제는 생성자를 만드는 시기부터 동작을 제대로 하지 않습니다.

Member(int a, int e) {
age = a;
etc = e;
}

호출은 아래와같이 합니다.

Member member = Member(20, 100);

혹은 아래와 같이 합니다.

Member member2(20,100);

혹은 아래와 같이 합니다.

Member * member1 = new Member(30,100);