언어/C&C++ 기본

[C++] Class

차가운오미자 2021. 6. 25. 10:41

Class

https://www.youtube.com/watch?v=2BP8NhxjrO0&list=PLlrATfBNZ98dudnM48yfGUldqGD0S4FFb&index=18&t=14s 

Class란?

데이터와 기능들을 묶기 위한 것. 

Class를 정의하고 instance를 만들어보기

#include <iostream>
#include <string>
using namespace std;

class Human {
	//definition of Human
	string name;
	int age;

}; // need a semicolon at the end

int main(void) {

	Human a; //객체(object, instance) 선언
	a.name = "Tara";
	a.age = 26;
}

이렇게 하면 a.name과 a.age에 에러가 뜬다(빨간 underline). Human::name에 엑세스할 수 없습니다. 라고 뜨는데, 이는 visibility와 관련된 문제이다.

기본적으로 모든 클라스는 안에 요소들을 private하게 지정한다. 그 말인 즉슨, class안에 정의된 함수로만 class안에 변수에 접근할 수 있다는 것이다. 하지만 액세스를 main에서 하고 싶기 때문에 class내에 name, age 변수들을 public 하게 선언해줘야 한다. 

#include <iostream>
#include <string>
using namespace std;

class Human {
public: // change visibility
	string name;
	int age;
};

int main(void) {

	Human a; //객체(object, instance) 선언
	a.name = "Tara";
	a.age = 26;
}

그럼 에러가 사라진다!

 

functions inside Class: METHODS

그냥 class과 무관하게 Human 객체의 위치를 변화시키는 move()라는 함수를 만들었다고 생각해보자. 

#include <iostream>
#include <string>
using namespace std;

class Human {
public:	
	string name;
	int age;
	int posx, posy;
}; 

void Move(Human& h, int x, int y) {
  h.posx += x;
  h.posy += y;
}

int main(void) {

	Human a; //객체(object, instance) 선언
	a.name = "Tara";
	a.age = 26;
    	Move(a, 1, 1);
}

이렇게 외부에 함수를 지정하면 좀 통일감이 떨어진다. 

Human이 움직이는 거니까 이 함수를 Human class 안에다가 정의해서 하나의 각 객체별로 함수에 접근할 수 있다. 

 

#include <iostream>
#include <string>
using namespace std;

class Human {
public:	
	string name;
	int age;
	int posx, posy;

	void Move(int x, int y) {
		// class내에 있는 메소드이므로, 굳이 Human&를 매개변수로 넘길 필요 없음  
		h.posx += x;
		h.posy += y;
	}
};

int main(void) {

	Human a; //객체(object, instance) 선언
	a.name = "Tara";
	a.age = 26;
	a.posx = 0;
	a.posy = 0;
	Move(1, 1);

	cout << a.posx << ", " << a.posy;
}

메소드를 선언할때, Human&을 매개변수로 넘길 필요가 없다. 왜냐면 이미 Human object 안에 있기 때문이다. 

 

이렇게 메소드를 이용해서 class내에 있는 데이터들에 접근할 수 있다. 

 

의의

클래스는 프로그래밍언어의 필수적인 요소가 아니다. C같은 경우에는 클래스 개념이 없지만 충분히 잘 사용할 수 있다. 단지, 클래스를 이용함으로써 프로그래머들이 좀더 쉽게 코드를 짜고, 유지보수할 수 있도록 해주는 것 뿐이다. 

 

Struct와의 비교

큰 차이가 없지만 visibility에서 차이가 있다. 

만약 변수들을 public하게 선언하지 않으면 내부 메소드를 이용하지 않고서는 변수에 접근할 수 없다. 

class는 visibility를 따로 지정해주지 않으면 모든것이 private하게 돌아간다.

하지만 struct는 기본적으로 모든 것이 public하다. 

코드에서 class를 struct으로 바꾸어도 큰 에러가 나오지 않는다. 그냥 visibility의 기본 설정이 다르다는 것이다. 

 

struct 가 C++에 있는 이유는 C와의 호환성(compatibility)를 고려한 것이다. C에는 class가 없기 때문이다. 하지만 struct는 존재한다. 만약 C++에 struct가 존재하지 않으면 C++ 컴파일러가 C를 읽을 때 struct가 뭔지 모를 것이다. 물론 #define을 이용해서 코드를 바꿔주면 되기도 하다. 

#define struct class

 

프로그래머로써 둘의 사용을 구분하는 것은 중요하다.

1. 그냥 단순하게, 나는 내 객체에 모든 것을 public하게 할 거야, 근데 public 선언을 하기 싫어. 하면 struct를 사용한다. 

2. 사람마다 스타일이 다르고, 각자의 구분 방식이 다르다. 자기 나름대로 어떤 것이 적합한지 판단을 내려서 사용하는 것이다. 동영상에 나온 The Cherno씨의 구분 방식은 다음과 같다. 

- struct 는 variable만 있을 때는 주로 사용한다. 딱히 특별한 기능(functionality)이 많지 않은 경우. 

- inheritance가 필요한 경우에는 class를 사용한다. (struct로부터 상속을 받는다던가 하면 에러가 날 수 있다)

 

Class 작성하기

동영상에서는 log 클래스를 만드는 과정을 함께 한다. log를 이용하면 전체 프로그램을 디버깅하는데 유용하다. log가 프린트되는 콘솔은 운영체제의 일부처럼 동작하기 때문에 프로그램에서 문제가 생겼을 경우(예를 들어 그래픽에 문제가 생겨서 게임이 멈춰버릴 경우)에도 작동할 것이라고 보장할 수 있다. 

1. write text

2. log level (error, warning, message/trace) - 일정 레벨에 해당되는 것만 프린트되도록 지정한다. 

 

코드 설명

실제로 로그 코드를 이렇게 만들면 큰일나지만 ㅎㅎ class를 설명하기에 좋은 예시로 든 것이라고 언급함.

#include <iostream>

class Log {

public:
	// 사람들이 숫자를 기억하고 있기는 힘드니까, 이렇게 레벨을 단어로 지정해준다.
	const int LogLevelError = 0;
	const int LogLevelWarning = 1;
	const int LogLevelInfo = 2;

private:
	// 설정된 로그 레벨을 담는 변수
	int m_LogLevel; // class member variable so put an m in front

public:
// 메인 함수에서 바로 call할 수 있도록 public으로 설정해준다. 

	// 로그 레벨을 설정하는 메소드
	void SetLevel(int level) {
		m_LogLevel = level;
	}
	// 에러 메시지를 출력하는 메소드, 로그레벨이 0(error)이상이어야 출력됨
	void Error(const char* mes) {
		if(m_LogLevel >= LogLevelError)
			std::cout << "[ERROR] " << mes << std::endl;
	}
	// 경고 메시지를 출력하는 메소드, 로그레벨이 1(warning)이상이어야 출력됨
	void Warn(const char* mes) {
		if (m_LogLevel >= LogLevelWarning)
			std::cout << "[WARNING] " << mes << std::endl;
	}
	// 정보 메세지를 출력하는 메소드, 로그레벨이 2(info)이상이어야 출력됨
	void Info(const char* mes) {
		if (m_LogLevel >= LogLevelInfo)
			std::cout << "[INFO] " << mes << std::endl;
	}
};

int main(void) {
	
	Log log;
	log.SetLevel(log.LogLevelWarning); //level을 그냥 1로 주기에는, 숫자를 기억하고 있어야 하니까 이렇게 변수를 이용한다. 
	log.Warn("this is log!");	
	log.Error("this is log!");
	log.Info("this is log!"); // 로그레벨이 워닝 이상으로 설정되어있어, 출력되지 않는다. 

}

 

'언어 > C&C++ 기본' 카테고리의 다른 글

[C++] ENUMS, Constructor, Destructor  (0) 2021.07.02
[C++] Static  (0) 2021.07.01
[C++] Header Files  (0) 2021.06.14
[C++] Variables, Functions, Pointers, References  (0) 2021.06.14
[C++] Linker  (0) 2021.06.14