앞서 본 구조체는 클래스의 일종이다.
그렇다면 클래스와 구조체는 어떤 차이점이 있을까?
키워드 struct 대신 class 를 사용하면 클래스가 된다.
그런데 클래스를 사용하면
CAr = run99={"run99",100,0};
와 같이 변수선언이 안되고 초기화를 클래스 밖에서 못한다.
이와 같이 말이다.
이렇듯 클래스는 정의를 하는 과정에서 각각의 변수 및 함수의 접근 허용범위를 별도로 선언해야 한다.
그리고 바로 이것이 키워드 struct를 이용해서 정의하는 구조체와 키워드 class를 이용하여 정의하는 클래스의 유일한 차이점이다!
접근제어와 관련된 선언을 추가해야한다하지않았는가!
C++의 접근제어 지시자는 다음과 같이 총 3가지 존재한다.
public,private만 보자 !
다음예제를 한번 보자
#include <iostream>
#include <cstring>
using namespace std;
namespace CAR_CONST {
enum
{
ID_LEN = 20, MAX_SPD=200, FUEL_STEP = 2,
ACC_STEP =10, BRK_STEP=10
};
}
class Car
{
private:
char gamerID[CAR_CONST::ID_LEN];
int fuelGauge;
int curSpeed;
public:
void InitMembers(char * ID, int fuel);
void ShowCarState();
void Accel();
void Break();
};
void Car::InitMembers(char * ID, int fuel)
{
strcpy(gamerID, ID);
fuelGauge = fuel;
curSpeed=0;
}
void Car::ShowCarState()
{
cout<<"소유자 ID : "<<gamerID<<endl;
cout<<"연료량 : "<<fuelGauge<<"%"<<endl;
cout<<"현재속도 : "<<curSpeed<<"km/s"<<endl<<endl;
}
void Car::Accel()
{
if(fuelGauge==0)
return;
else
fuelGauge-=CAR_CONST::FUEL_STEP;
if((curSpeed+CAR_CONST::ACC_STEP)>=CAR_CONST::MAX_SPD)
{
curSpeed = CAR_CONST::MAX_SPD;
return;
}
curSpeed+=CAR_CONST::ACC_STEP;
}
void Car::Break()
{
if (curSpeed<CAR_CONST::BRK_STEP) {
curSpeed=0;
return;
}
curSpeed = CAR_CONST::BRK_STEP;
}
int main(void)
{
Car run99;
run99.InitMembers("run99", 100);
run99.Accel();
run99.Accel();
run99.Accel();
run99.ShowCarState();
run99.Break();
run99.ShowCarState();
return 0;
}
이를 통해 다음과 같은 사실을 알 수 있다.
- 접근제어 A가 선언되면 그 이후에 등장하는 변수나 함수는 A에 해당하는 범위내에서 접근 가능하다.
- 그러나! 새로운 접근제어 지시자 B가 선언되면 이후는 B에 해당하는 범위 내에서 접근 가능!
- 함수의 정의를 클래스 밖으로 빼도, 이는 클래스의 일부이기 때문에, 함수 내에서는 private으로 선언된 변수에 접근 가능하다 !!!!
- struct : public 기본
- class : private 기본 !
접근제어 지시자는 특정 위치정보를 알리는 레이블 이기에 세미콜론이 아닌 콜론이 붙는다.
그래서 위에 예제에서 run99는 변수가 아닌 객체이다.
어떠한 프로그램이건 하나의 파일에 모든 걸 담지 않는다!
특히 C++은 클래스 별로 헤더,소스 파일을 생성하기에 매우 많은 수의 파일이 만들어진다.
클래스 Car를 대상으로 파일을 나눌때에는 보통 다음과 같이 파일을 구분한다.
- Car.h 클래스의 선언을 담는다.
- Car.cpp 클래스의 정의를 담는다.
클래스 선언은 다음과 같다.
이는 클래스를 구성하는 외형적인 틀을 보여준다.
클래스의 정의는 다음과 같다.
이는 다른 문장의 컴파일에 필요한 정보를 가지고 있지않다.
따라서 함수의 정의는 컴파일 된 이후에, 링커에 의해 하나의 실행파일로 묶이기만 하면 된다.
그럼 지금까지 배운 내용을 토대로 앞선 예제를 쪼개보자!!
Car.hpp
//
// Car.hpp
// 1_practice
//
// Created by 서희찬 on 2021/05/10.
//
#ifndef Car_hpp
#define Car_hpp
namespace CAR_CONST {
enum
{
ID_LEN = 20, MAX_SPD=200, FUEL_STEP = 2,
ACC_STEP =10, BRK_STEP=10
};
}
class Car
{
private:
char gamerID[CAR_CONST::ID_LEN];
int fuelGauge;
int curSpeed;
public:
void InitMembers(char * ID, int fuel);
void ShowCarState();
void Accel();
void Break();
};
#endif /* Car_hpp */
Car.cpp
//
// Car.cpp
// 1_practice
//
// Created by 서희찬 on 2021/05/10.
//
#include <iostream>
#include <cstring>
#include "Car.hpp"
using namespace std;
void Car::InitMembers(char * ID, int fuel)
{
strcpy(gamerID, ID);
fuelGauge = fuel;
curSpeed=0;
}
void Car::ShowCarState()
{
cout<<"소유자 ID : "<<gamerID<<endl;
cout<<"연료량 : "<<fuelGauge<<"%"<<endl;
cout<<"현재속도 : "<<curSpeed<<"km/s"<<endl<<endl;
}
void Car::Accel()
{
if(fuelGauge==0)
return;
else
fuelGauge-=CAR_CONST::FUEL_STEP;
if((curSpeed+CAR_CONST::ACC_STEP)>=CAR_CONST::MAX_SPD)
{
curSpeed = CAR_CONST::MAX_SPD;
return;
}
curSpeed+=CAR_CONST::ACC_STEP;
}
void Car::Break()
{
if (curSpeed<CAR_CONST::BRK_STEP) {
curSpeed=0;
return;
}
curSpeed = CAR_CONST::BRK_STEP;
}
Main.cpp
#include "Car.hpp"
using namespace std;
int main(void)
{
Car run99;
run99.InitMembers("run99", 100);
run99.Accel();
run99.Accel();
run99.Accel();
run99.ShowCarState();
run99.Break();
run99.ShowCarState();
return 0;
}
성공~
컴파일 과정에서 함수의 호출문을 대체해야기 때문에 !
헤더파일에 함께 정의되어야 한다.
계산기 기능을 Calculator 클래스를 정의해서 만들어보자 !
Calculator.hpp
Calculator.cpp
Main.c
순서대로 올리겠다.
//
// Calculator.hpp
// Calculator_3
//
// Created by 서희찬 on 2021/05/10.
//
#ifndef Calculator_hpp
#define Calculator_hpp
#include <iostream>
using namespace std;
class Calculator
{
private:
int numofAdd;
int numofAMin;
int numofMuul;
int numofDiv;
public:
void init();
double Add(double num1, double num2);
double Div(double num1, double num2);
double Min(double num1, double num2);
double Mul(double num1, double num2);
void showOpCount();
};
#endif /* Calculator_hpp */
//
// Calculator.cpp
// Calculator_3
//
// Created by 서희찬 on 2021/05/10.
//
#include <iostream>
#include "Calculator.hpp"
using namespace std;
void Calculator::init()
{
numofAdd = 0;
numofDiv = 0;
numofMuul = 0;
numofAMin = 0;
}
double Calculator::Add(double num1, double num2)
{
numofAdd++;
return num1+num2;
}
double Calculator::Div(double num1, double num2)
{
numofDiv ++;
return num1/num2;
}
double Calculator::Min(double num1, double num2)
{
numofAMin++;
return num1 - num2;
}
double Calculator::Mul(double num1, double num2)
{
numofMuul++;
return num1 * num2;
}
void Calculator::showOpCount()
{
cout<<numofAdd<<endl;
cout<<numofDiv<<endl;
cout<<numofMuul<<endl;
cout<<numofAMin<<endl;
}
//
// main.cpp
// Calculator_3
//
// Created by 서희찬 on 2021/05/10.
//
#include <iostream>
#include "Calculator.hpp"
using namespace std;
int main(void)
{
Calculator cal;
cal.init();
cout<<cal.Add(3.2, 2.4)<<endl;
cout<<cal.Min(3.2, 2.4)<<endl;
cout<<cal.Mul(3.2, 2.4)<<endl;
cout<<cal.Div(3.2, 2.4)<<endl;
cal.showOpCount();
return 0;
}
굿굿!
문자열 정보를 내부에 저장하는 Printer라는 이름의 클래스를 디자인하자. 이클래스의 두 가지 기능은 다음과 같다.
문자열 저장
문자열 출력
아래의 main함수에 부합하는 Printer class를 정의하자 !
#include <iostream>
using namespace std;
class Printer
{
private:
char str[100];
public:
void SetString(char * s);
void ShowString();
};
void Printer::SetString(char * s)
{
strcpy(str, s);
}
void Printer::ShowString()
{
cout<<str<<endl;
}
int main(void)
{
Printer pnt;
pnt.SetString("Hello World");
pnt.ShowString();
pnt.SetString("I Love C++");
pnt.ShowString();
return 0;
}
쨘 !