안녕하세요! 오늘도 어김없이 C++ 학습 내용 정리를 시작하겠습니다.
저번 주 금요일로 하여금 Unreal Blueprint와 C 언어 기초 강의가 끝났기 때문에 이번 주는 계속해서 C++를 학습하는 시간을 가지게 됩니다.
그럼 집중해서 학습해 보도록 하겠습니다.
클래스(Class)
C 와 C++의 가장 큰 차이점은 C 언어는 절차지향언어 이고 C++ 언어는 객체지향언어 라는 점입니다.
절차지향언어는 위에서 아래로 순차적으로 코드를 실행하고 객체지향언어는 객체 단위로 코드를 실행합니다.
그래서 C++ 부터는 객체라는 개념을 도입하고 그 중간에 클래스(Class)가 있습니다.
객체지향에 대해서는 다음 파트에서 더 자세히 다뤄보고 클래스에 대해 학습 하겠습니다.
클래스는 객체를 만드는 설계도 혹은 청사진, 붕어빵 틀 등에 비유할 수 있습니다.
즉, 어떤 객체를 만들기 위한 틀을 의미 합니다. 그리고 클래스를 통해 선언해서 메모리가 할당되면 그것을 객체라고 부릅니다.
그리고 클래스를 통해 선언해서 메모리가 할당되는 것을 인스턴스화 라고도 표현합니다.
기본 형태는 class 클래스명 { 클래스 내용 }; 의 형태를 갖춥니다.
선언할 때는 클래스명 객체명; 으로 인스턴스화 할 수 있습니다.
클래스 안의 변수, 함수, 등을 멤버(Member)라고 하고 변수는 멤버 변수, 함수는 멤버 함수 등으로 불립니다.
외부에서 클래스의 멤버에 아무나 접근 가능하면 보안이 너무 취약합니다.
그래서 접근제어를 해줄 수 있습니다. 접근을 제어해주는 명령어를 "접근 지정자"라고 부르며, 접근 지정자에는 public, private, protected 가 있습니다.
public은 클래스의 외부, 내부 어느 곳에서도 접근이 가능하도록 설정하는 접근 지정자 입니다.
private은 클래스의 내부에서만 접근이 가능하도록 설정하는 접근 지정자 입니다.
protected는 클래스의 내부와 클래스를 상속하고 있는 곳에서 접근이 가능하도록 설정하는 접근 지정자 입니다.
외부에서 클래스 안의 함수를 정의할 때는 ::연산자를 사용하여 클래스 안의 함수를 정의한다고 명시해주어야 합니다.
ex)
#include <iostream>
#include <string>
using namespace std;
class Student
{
public:
void setStudent(string tempName, int tempGrade, int tempStudentNumber);
string getName(void);
int getGrade(void);
int getStudentNumber(void);
private:
string name;
int grade;
int studentNumber;
};
void Student::setStudent(string tempName, int tempGrade, int tempStudentNumber)
{
name = tempName;
grade = tempGrade;
studentNumber = tempStudentNumber;
}
string Student::getName(void)
{
return name;
}
int Student::getGrade(void)
{
return grade;
}
int Student::getStudentNumber(void)
{
return studentNumber;
}
int main()
{
Student s;
string tempName;
int tempGrade;
int tempStudentNumber;
cout << "NAME(string): ";
cin >> tempName;
cout << "GRADE(int): ";
cin >> tempGrade;
cout << "STUDENT NUMBER(int): ";
cin >> tempStudentNumber;
s.setStudent(tempName, tempGrade, tempStudentNumber);
cout << "\n*Student Information*" << endl;
cout << "NAME: " << s.getName() << endl;
cout << "GRADE: " << s.getGrade() << endl;
cout << "STUDENT NUMBER: " << s.getStudentNumber() << endl;
return 0;
}
그럼 "private인 멤버 변수들은 값을 어떻게 지정 해주어야 하는가?"라는 의문이 드실 수 있습니다.
이 때 사용하는 것이 Getter와 Setter 입니다.
말 그대로 Getter는 값을 가져오는 함수 즉, 읽기 전용 이고 Setter는 값을 저장하는 함수 즉, 쓰기 전용 입니다.
위의 클래스에서는 setStudent() 함수가 Setter에 해당하고 getName(), getGrade(), getStudentNumber() 함수가 Getter에 해당합니다.
Getter와 Setter를 사용하는 이유는 의도하지 않은 곳에서 값이 변경되거나 쓰이는 것을 방지하기 위해서며, 대표적인 예시로 Setter 함수에서 조건문을 통해 원하는 값의 범위를 지정하거나 검사한 후에 멤버 변수에 값을 적용할 수 있습니다.
뿐만아니라 코드를 읽을 때, 어디에서 객체의 변수가 변경되었고 어디에서 쓰였는지 보기 수월해져, 가독성이 올라갑니다.
클래스의 생성자(constructor)
객체가 생성될 때, 자동으로 한 번만 실행되는 멤버 함수 입니다.
보통 생성자는 멤버 변수의 초기화 혹은 객체가 동작할 준비를 하기 위해 사용됩니다.
기본 형태는 클래스명( 매개변수 ) { 내용 } 의 형태를 갖춥니다.
생성자의 경우 반환형을 아예 가지지 않습니다. (void와 다릅니다.)
생성자가 매개변수를 가지는 경우, 클래스를 인스턴스화 할 때 객체명 뒤에 인자 값을 넣어주어야 합니다.
즉, 클래스명 객체명( 인자 ); 의 형태로 선언됩니다.
클래스를 객체로 인스턴스화 할 때, 필요에 따라 인자를 받고 그 외에는 기본 값으로 설정해 줄 때는 생성자를 정의할 때, 매개변수에 기본매개변수를 설정해주면 됩니다.
형태는 클래스명 (자료형 변수명 = 변수기본값) { 내용 } 의 형태를 갖춥니다.
객체를 선언할 때는 클래스명 객체명; 으로 선언할 경우, 생성자의 인자로 기본매개변수가 입력되고 클래스명 객체명(인자); 로 선언할 경우 생성자에 인자 값이 입력되게 됩니다.
ex)
#include <iostream>
#include <string>
using namespace std;
class Student
{
public:
Student(string defaultName, int defaultGrade, int defaultStudentNumber);
void setStudent(string tempName, int tempGrade, int tempStudentNumber);
string getName(void);
int getGrade(void);
int getStudentNumber(void);
private:
string name;
int grade;
int studentNumber;
};
Student::Student(string defaultName = "None", int defaultGrade = 0, int defaultStudentNumber = 0)
{
name = defaultName;
grade = defaultGrade;
studentNumber = defaultStudentNumber;
}
void Student::setStudent(string tempName, int tempGrade, int tempStudentNumber)
{
name = tempName;
grade = tempGrade;
studentNumber = tempStudentNumber;
}
string Student::getName(void)
{
return name;
}
int Student::getGrade(void)
{
return grade;
}
int Student::getStudentNumber(void)
{
return studentNumber;
}
int main()
{
Student s1("hongin", 1, 1);
Student s2;
string tempName;
int tempGrade;
int tempStudentNumber;
cout << "NAME(string): ";
cin >> tempName;
cout << "GRADE(int): ";
cin >> tempGrade;
cout << "STUDENT NUMBER(int): ";
cin >> tempStudentNumber;
s2.setStudent(tempName, tempGrade, tempStudentNumber);
cout << "\n\n*Student Information*" << endl;
cout << "1." << endl;
cout << "NAME: " << s1.getName() << endl;
cout << "GRADE: " << s1.getGrade() << endl;
cout << "STUDENT NUMBER: " << s1.getStudentNumber() << endl;
cout << "2." << endl;
cout << "NAME: " << s2.getName() << endl;
cout << "GRADE: " << s2.getGrade() << endl;
cout << "STUDENT NUMBER: " << s2.getStudentNumber() << endl;
return 0;
}
생성자에 매개변수 입력을 받을 때는 되도록 기본매개변수를 설정해주는 것이 좋습니다.
생성자의 매개변수에 기본매개변수를 설정하지 않고 클래스를 만들 경우, 클래스의 객체를 선언할 때 인자를 모두 입력해주지 않으면 오류가 발생할 수 있기 때문입니다.
헤더파일(h.header)
연관성이 있는 클래스 끼리 모아둬서 필요한 클래스를 빨리 찾을 수 있습니다. 그리고 클래스가 어떻게 선언되어 있는지 빠르게 확인할 수 있습니다.
그럼 "왜? 선언만 하고 정의는 하지 않는가?"에 대한 이유는 정의까지 할 수 있지만 헤더파일을 여러곳에서 include하고 그것이 섞이다보면 함수가 중복정의될 가능성이 있기 때문에 헤더파일에는 클래스를 선언만 해두고 클래스 멤버의 정의는 헤더를 include한 cpp 소스코드 파일 안에서 하는 경우가 많습니다.
위의 코드를 header파일(헤더파일)와 cpp파일(소스코드파일)로 분리하여 구현 해보겠습니다.
ex)
#ifndef STUDENT_H_
#define STUDENT_H_
#include <string>
using namespace std;
class Student
{
public:
Student(string defaultName, int defaultGrade, int defaultStudentNumber);
void setStudent(string tempName, int tempGrade, int tempStudentNumber);
string getName(void);
int getGrade(void);
int getStudentNumber(void);
private:
string name;
int grade;
int studentNumber;
};
#endif
student.h 로 저장하였습니다.
#include "student.h"
#include <iostream>
using namespace std;
Student::Student(string defaultName = "None", int defaultGrade = 0, int defaultStudentNumber = 0)
{
name = defaultName;
grade = defaultGrade;
studentNumber = defaultStudentNumber;
}
void Student::setStudent(string tempName, int tempGrade, int tempStudentNumber)
{
name = tempName;
grade = tempGrade;
studentNumber = tempStudentNumber;
}
string Student::getName(void)
{
return name;
}
int Student::getGrade(void)
{
return grade;
}
int Student::getStudentNumber(void)
{
return studentNumber;
}
int main()
{
Student s1("hongin", 1, 1);
Student s2;
string tempName;
int tempGrade;
int tempStudentNumber;
cout << "NAME(string): ";
cin >> tempName;
cout << "GRADE(int): ";
cin >> tempGrade;
cout << "STUDENT NUMBER(int): ";
cin >> tempStudentNumber;
s2.setStudent(tempName, tempGrade, tempStudentNumber);
cout << "\n\n*Student Information*" << endl;
cout << "1." << endl;
cout << "NAME: " << s1.getName() << endl;
cout << "GRADE: " << s1.getGrade() << endl;
cout << "STUDENT NUMBER: " << s1.getStudentNumber() << endl;
cout << "2." << endl;
cout << "NAME: " << s2.getName() << endl;
cout << "GRADE: " << s2.getGrade() << endl;
cout << "STUDENT NUMBER: " << s2.getStudentNumber() << endl;
return 0;
}
헤더 파일을 include하여 main.cpp 파일에서 정의한 후 사용하였습니다.
이 경우, student.h 헤더파일에서 string 라이브러리를 include하고 있기 때문에 main.cpp 에서는 따로 string 라이브러리를 include하지 않아도 됩니다.
전처리기 #include, #ifndef, #define, #endif 에 대해서는 나중에 알아보겠습니다.
상속
부모가 자식에게 특성을 물려주듯, 부모가 되는 클래스에 선언되어 있는 멤버들을 자식이 되는 클래스에서 따로 선언하지 않아도 멤버로 가질 수 있는 기능입니다.
상속 대상이 되는 클래스를 기본 클래스 또는 부모 클래스 라고 합니다.
상속을 받는 클래스를 파생 클래스 또는 자식 클래스 라고 합니다.
예시를 통해 코드를 직접 보면서 학습 해보겠습니다.
#ifndef VEHICLE_H_
#define VEHICLE_H_
#include <string>
using namespace std;
class Vehicle
{
protected:
string color;
int passengerCapacity;
public:
Vehicle(string defaultColor = "White", int defaultPassenger = 2);
void setColor(string tempColor);
void setPassenger(int tempPassenger);
string getColor(void);
int getPassenger(void);
};
class Sedan : public Vehicle
{
private:
bool isSunRoof;
int numberOfDoor;
public:
Sedan(string defaultColor = "White", int defaultPassenger = 2, bool defaultSunRoof = false, int defaultNumberOfDoor = 4);
void setSunRoof(bool tempSunRoof);
void setNumberOfDoor(int tempNumberOfDoor);
bool getSunRoof(void);
int getNumberOfDoor(void);
};
class Truck : public Vehicle
{
private:
int carryingCapacity;
public:
Truck(string defaultColor = "White", int defaultPassenger = 2, int defaultCarry = 1);
void setCarryingCapacity(int tempCarryingCapacity);
int getCarryingCapacity(void);
};
#endif
vehicle.h 헤더파일을 통해 기본 클래스 Vehicle과 파생 클래스 Sedan, 파생 클래스 Truck을 선언 하였습니다.
파생 클래스(자식 클래스)를 선언하는 기본 형태는 class 파생 클래스 명 : 기본 클래스 명 { 클래스 내용 }; 의 형태를 갖춥니다.
이렇게 파생 클래스(자식 클래스)를 선언하면 기본 클래스(부모 클래스)의 멤버 변수와, 멤버 함수가 파생 클래스(자식 클래스)에 상속되어 생성됩니다.
#include "vehicle.h"
#include <iostream>
using namespace std;
// 상속
Vehicle::Vehicle(string defaultColor, int defaultPassenger)
{
color = defaultColor;
passengerCapacity = defaultPassenger;
}
void Vehicle::setColor(string tempColor)
{
color = tempColor;
}
void Vehicle::setPassenger(int tempPassenger)
{
passengerCapacity = tempPassenger;
}
string Vehicle::getColor(void)
{
return color;
}
int Vehicle::getPassenger(void)
{
return passengerCapacity;
}
Sedan::Sedan(string defaultColor, int defaultPassenger, bool defaultSunRoof, int defaultNumberOfDoor):Vehicle(defaultColor, defaultPassenger)
{
isSunRoof = defaultSunRoof;
numberOfDoor = defaultNumberOfDoor;
}
void Sedan::setSunRoof(bool tempSunRoof)
{
isSunRoof = tempSunRoof;
}
void Sedan::setNumberOfDoor(int tempNumberOfDoor)
{
numberOfDoor = tempNumberOfDoor;
}
bool Sedan::getSunRoof(void)
{
return isSunRoof;
}
int Sedan::getNumberOfDoor(void)
{
return numberOfDoor;
}
Truck::Truck(string defaultColor, int defaultPassenger, int defaultCarry):Vehicle(defaultColor, defaultPassenger)
{
carryingCapacity = defaultCarry;
}
void Truck::setCarryingCapacity(int tempCarryingCapacity)
{
carryingCapacity = tempCarryingCapacity;
}
int Truck::getCarryingCapacity(void)
{
return carryingCapacity;
}
int main(void)
{
Sedan s;
s.setColor("Black");
s.setPassenger(4);
s.setNumberOfDoor(4);
cout << s.getColor() << ", " << s.getPassenger() << ", " << s.getNumberOfDoor() << endl;
return 0;
}
main.cpp 소스코드파일에서 각 클래스의 멤버 함수를 정의하였고 클래스 Vehicle을 상속한 파생 클래스 Sedan과 파생 클래스 Truck의 생성자에는 멤버 초기화 리스트를 통해 상속 받은 Vehicle의 생성자 Vehicle을 호출한 것을 확인할 수 있다.
멤버 초기화 리스트는 생성자( 매개변수 ) : 함수명( 인자 ), 변수명( 초기화 값 ) { 생성자 내용 } 의 형태를 갖춥니다.
그리고 멤버 초기화 리스트에서 실행되는 함수 혹은 변수는 생성자의 내용(생성자의 코드) 보다 먼저 실행됩니다.
오늘은 여기까지 학습하였습니다!
상속에 대해서는 조금 더 이해한 후에 다음 글에서 정리하도록 하겠습니다.
내일도 힘내서 열심히 공부하겠습니다!
'[내일배움캠프] 본 과정 학습내용' 카테고리의 다른 글
| [내배캠] 10일차 C++ 학습 내용 정리 (0) | 2026.07.09 |
|---|---|
| [내배캠] 9일차 C++ 학습 내용 정리 (0) | 2026.07.08 |
| [내배캠] 5일차 Unreal Blueprint 내용 정리(2) 및 7일차 C++ 학습 내용 정리 (0) | 2026.07.06 |
| [내배캠] 5일차 Unreal Blueprint 내용 정리(1) (0) | 2026.07.03 |
| [내배캠] 4일차 Unreal Blueprint로 적 구현과 C언어 기초 (0) | 2026.07.01 |