암묵적인 룰
일반적으로 많은 C++ 개발자는 헤더파일 한개와 소스파일 한개를 이용해 클래스를 정의하여 사용한다.
즉 한개의 클래스는 한개의 헤더파일과 한개의 소스파일을 갖게 된다.
이것은 언어에서 강제하는 사항은 아니지만 그렇게 하는 것이 미덕이다.
함수의 선언과 몸체를 분리할 필요가 있는 이유
animal.h
#include <cstring> // strcpy를 사용하기 위해서는 헤더파일 그 자체에 include되어 있어야한다. class Animal { public: int legs; char name[50]; Animal(int legs, const char* name) { this->legs = legs; strcpy(this->name, name); } void printInfo() { printf("동물의 이름: %s, 동물의 다리: %d\n", name, legs); } }; |
main_header.h
#define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <cstring> #include <cmath> #include <ctime> #include <cstdlib> int count = 0; // 종료조건 void hoo(); void goo(); void foo(); |
main.cpp
#include "main_header.h" #include "animal.h" int main() { foo(); Animal* animal = new Animal(2, "닭"); animal->printInfo(); return 0; } void hoo() { printf("hoo()\n"); count++; foo(); } void goo() { printf("goo()\n"); count++; hoo(); } void foo(){ // 선언만 해준 상태 if (count <= 10) { printf("foo()\n"); goo(); count++; } } /* header 파일에 foo(); 이런식으로 함수를 선언해주면 몸체는 여기 있구나 하고 c++ 컴파일러가 연결해준다. 그거를 Linking이라 부른다. 그래서 foo()에서 goo()를 불러도 몸체가 위에 있건 아래에 있건 상관없이 이미 선언 부분이 나와있어 이 함수를 찾아갈 수 있게 된다. cpp파일을 기준으로 컴파일 하기 때문에 위쪽의 선언부에 함수의 선언이 있다면 그 선언된 함수와 실체 몸체를 갖고 있는 함수를 연결해준다. 선언을 보고 몸체를 찾아가기 */ |
클래스의 멤버함수 분리
클래스에서 멤버함수의 선언과 정의를 분리하기 위해서는
클래스에는 함수의 선언 부분만 남겨둔 이후에
소스파일에서 해당 클래스의 함수를 정의하면 된다.
다음과 같은 방법으로 소스파일에서 멤버함수를 정의할 수 있다.
클래스명::멤버함수명(파라미터) { ...
}
헤더파일의 중복 정의를 막기 위해 사용하는 매크로
: 클래스의 중복 정의를 막아주기 위해서 매크로 전처리기를 자동으로 삽입해준 것, 헤더를 두 번 include 하지 않는다
1.
#pragma once
2.
#ifndef __HOUSE_H__
#define __HOUSE_H__
#endif
house.h
#ifndef __HOUSE_H__ #define __HOUSE_H__ class Animal; // 이 클래스가 어디있는지 모르지만 어딘가에 있다, 이 클래스를 나중에 다른 cpp파일에서 몸체와 다른 헤더파일에서 선언을 찾을 수 있다. //#include "animal.h" 대신 전방선언 가능 class House{ public: Animal* animal; //Animal 포인터를 할당하는 함수 void setAnimal(Animal* a); }; class Goo; // 이런식으로 클래스 전방선언을 하게 되면 Foo의 입장에서 Goo라는 녀석이 어딘가에 있긴있구나 라는 것을 위쪽을 통해 알 수 있다 class Foo { public: Goo* g; }; class Goo { public: Foo* f; }; #endif |
house.cpp
#include "house.h" void House::setAnimal(Animal* a) { this->animal = a; } |
animal.h
#ifndef __ANIMAL_H__ #define __ANIMAL_H__ class Animal { public: int legs; char name[50]; Animal(int legs, const char* name); // 선언만 있다. void printInfo(); }; #endif |
animal.cpp
#include "main_header.h" #include "animal.h" Animal::Animal(int legs, const char* name) { this->legs = legs; strcpy(this->name, name); } // 생성자의 몸체가 animal.cpp에 만들어짐 void Animal::printInfo() { printf("동물의 이름: %s, 동물의 다리: %d\n", name, legs); } // 클래스 내부 함수의 선언과 몸체를 나눌 수가 있게 됨 |
person.h
#ifndef __PERSON_H__ #define __PERSON_H__ #include "animal.h" class Person : Animal{ public: char regist_no[50]; Person(const char* regist_no, const char* person_name); void printInfo(); }; #endif |
person.cpp
#include "main_header.h" #include "person.h" Person::Person(const char* regist_no, const char* person_name):Animal(2, person_name){ strcpy(this->regist_no, regist_no); } void Person:: printInfo() { printf("사람이름 : %s, 주민등록번호 : %s\n", name, regist_no); } |
main.cpp
#include "main_header.h" #include "animal.h" #include "person.h" int main() { Animal* animal = new Animal(4, "소"); animal->printInfo(); Person* person = new Person("1234-5678", "김말똥"); person->printInfo(); return 0; } |
과제형 연습 프로그래밍
Header.h 에 있는 int displayData[GRID_HEIGHT][GRID_WIDTH] = { 0, };을
extern int displayData[GRID_HEIGHT][GRID_WIDTH]; 으로 바꾼다.
그리고 Source.cpp에
int displayData[GRID_HEIGHT][GRID_WIDTH] = { 0, }; 로 바꾼다.
함수만 선언과 몸통을 분리하고 각각의 클래스마다 각각의 헤더파일과 각각의 소스파일만 만들면 된다.
Display.h를 만들어
#ifndef __DISPLAY_H__
#define __DISPLAY_H__
#include "Header.h"
사이에 Display 함수를 붙여넣기
#endif
GameEngine, Header.h도 똑같이 바꿔준다
그 후 Source.cpp에 #include "Display.h", #include "GameEngine.h"를 적어준다.
이 상태에서 Display.cpp 만들어 #include "Display.h" 한 후
Display.h 에는 함수를 선언만 해주고
Display.cpp 에서 함수 내용을 붙여 넣어준다.
void Display::draw() { 내용 붙여넣기 }
GameEngine.cpp도 만들어서 마찬가지로 함수만 찾아내어 복사 붙여넣기 하면 됨
init, next, canGoDown, isLineFilled, gameOverDecision, makeUserBlock, trans, rotate 등등 모든 함수
void next (float dt, char keyboardInput);
에 next가 초록줄이 그어지면 ctrl .(온점) 을 누르고 엔터치면 자동으로 만들어준다. 그걸 저장하고 cpp로 가면 있다
TetrisHelper.h도..
TetrisHelper.h에 있는 KEY_EVENT_RECORD krec;를
TetrisHelper.cpp로 옮겨준다.
'C++' 카테고리의 다른 글
c++ 11 (실행구조 / Bitwise / 순수 가상함수) (0) | 2022.02.17 |
---|---|
c++ 10 (C++ 의 컴파일에 관하여 - LNK 오류에 대처하기) (0) | 2022.02.14 |
c++ 8 (추가 개념 정리 / 피드백) (0) | 2022.02.05 |
c++ 6 (열거형 - 가독성을 위한 타입) (0) | 2022.01.23 |
c++ 5 (가상함수 - Java, C# 등 다른 언어의 개념 까지 ) (0) | 2022.01.16 |