[C++] 클리스 선언과 사용법


Study/C , C++ , MFC  2020. 3. 17. 00:39

안녕하세요. 명월입니다.


이 글은 C++에서 클리스 선언과 사용법에 대한 글입니다.


C++에서에서 클래스를 사용하기 전에 먼저 해더의 역할을 먼저 설명하겠습니다. 해더를 좀 더 제대로 활용하기 위해서는 전처리문을 알아야 하는데, 그건 나중에 따로 정리해서 설명하겠습니다.

C++은 Java와 C#과 다르게 int main()함수만 있어도 실행이 됩니다. 이게 무슨 말이냐면 Java나 C#은 package나 네임스페이스 안의 클래스 안의 static void main()으로 실행합니다.

즉, 최소 단위가 클래스 단위인데 C++은 딱 함수만 있어도 실행이 됩니다.


이때 함수의 순서가 필요한데... main 함수가 가장 밑에 놓입니다. main 함수가 사용자 함수보다 위에 있으면 에러가 발생합니다.

이유는 main 함수를 읽을 때, 함수가 등록되어 있지 않다고 판단하기 때문입니다.


그럼 항상 함수를 main 함수 위에 두어야 하는 것인가에 대해서 그것도 아닙니다. "함수 선언"이라고 함수가 무엇이 있을 것이라고 미리 선언을 하게 되면 뒤에 두어도 됩니다.

// 해더 선언
#include <stdio.h>
#include <iostream>
using namespace std;
// 함수 선언!!
void print();
// 실행 함수
int main()
{
  // print() 함수 호출
  print();
  return 0;
}
// print 함수
void print()
{
  // 콘솔 출력
  cout << " hello world " << endl;
}

main 위에 main뒤에 무슨 함수가 있을 것인지 함수 선언을 하게 되면 에러 없이 출력이 됩니다.


그럼 헤더는 어떻게 만드느냐면 헤더 선언과 함수 선언을 그대로 해더 파일에 넣고 위에는 해더 파일을 선언만 합니다.

// 중복 검사 전처리문
#pragma once
// 해더 선언
#include <stdio.h>
#include <iostream>
using namespace std;
// 함수 선언!!
void print();
// 헤더 선언
#include "Example.h"
// 실행 함수
int main()
{
  // print() 함수 호출
  print();
  return 0;
}
// print 함수
void print()
{
  // 콘솔 출력
  cout << " hello world " << endl;
}

실행 결과입니다.

#pragma once는 해더의 중복 호출을 막는 것입니다. 이걸 이해하려면 전처리문을 알아야 하는데, 이것도 따로 정리해서 설명하겠습니다.


헤더 파일를 알았으니 이제 클래스를 설명하겠습니다. 클래스는 이 함수 선언과 관계가 있어서 그렇습니다.

소스 파일에서 마우스 오른쪽을 누르면 추가에서 클래스 추가 항목이 있습니다.

클래스 이름을 넣으면 소스 파일(.cpp)과 해더 파일(.h)이 생성할 수 있습니다.

// 중복 검사 전처리문
#pragma once
// 해더 선언
#include <stdio.h>
#include <iostream>
using namespace std;
// 클래스 함수 선언
class Node
{
// 접근 제한자 (내부만)
private:
  // 맴버 변수
  int data;
// 접근 제한자 (내부, 상속)
protected:
  // 함수 선언
  void test();
// 접근 제한자 (내부, 상속, 외부)
public:
  // 프로퍼티
  void setData(int data);
  int getData();
  // 함수 선언
  void print();
};
// 해더 선언
#include "Node.h"
// 함수 선언 (클래스 명::함수명) - getter 프로퍼티
int Node::getData()
{
  return data;
}
// 함수 선언 (클래스 명::함수명) - setter 프로퍼티
void Node::setData(int data)
{
  // 내부 맴버 변수는 화살표로 찾아간다.
  this->data = data;
}
// 함수 선언 (클래스 명::함수명)
void Node::test()
{
  // 콘솔 출력
  cout << " data : " << this->data << endl;
}
// 함수 선언 (클래스 명::함수명)
void Node::print()
{
  // test함수 호출
  this->test();
}
// 함수 선언
#include <stdio.h>
#include <iostream>
// 사용할 클래스 선언
#include "Node.h"
using namespace std;
// 실행 함수
int main()
{
  // 클래스를 statck으로 선언
  Node node1;
  // statck으로 선언하면 함수 호출을 「.」으로 한다.
  // setData로 5를 넣는다.
  node1.setData(5);
  // print함수 호출
  node1.print();
  
  // 클래스를 heap으로 선언
  Node* node2 = new Node();
  // heap으로 선언하면 함수 호출을 「->」으로 한다.
  // setData로 10를 넣는다.
  node2->setData(10);
  // print함수 호출
  node2->print();
  // heap으로 선언한 건 delete로 메모리 해제한다.
  delete node2;
  return 0;
}

실행화면입니다.

여기서 클래스 해더에는 클래스의 맴버 변수와 함수 선언이 모두 들어갑니다. 클래스 소스에는 함수의 구현 소스가 들어갑니다. 아까처럼 함수 선언이 해더 파일에 작성되고, 구현 소스는 소스 파일에 작성됩니다.

main 함수에서 Node 클래스를 선언해서 사용할 수 있습니다.


C++에서는 클래스를 사용하는 방법에 대해서 다른 언어와 다르게 재미있는 방법이 있습니다.

Node node1의 경우는 stack 메모리에 클래스를 선언하여 사용합니다. 그런데 이 클래스는 statck에서 호출되었으니 따로 메모리 해제할 필요가 없습니다.

링크 - [C++] 배열과 포인터(메모리 주소) 그리고 할당(new){stack과 heap에 대해서}

node1은 statck 내부에서 어떤 방식으로 사용되도 문제는 없는데 stack 영역이 끝나면 메모리가 해제되니 다른 곳에서 해제하거나 stack 영역을 벗어나서 사용하면 버그가 발생할 수도 있습니다.

반대로 node2는 new를 사용해서 할당하였기 때문에 delete로 해제하지 않으면 메모리 누수(memory leak)가 발생할 수 있습니다.


여기까지 C++에서 클리스 선언과 사용법에 대한 글이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.