c++구조체
c++구조체는 함수를 삽입할 수 있습니다.
//구조체에 삽입되기 이전의 함수
void ShowCarState(const Car &car)
{
cout<<"소유자ID: "<<car.gamerID<<endl;
cout<<"연료량: "<<car.fuelGauge<<"%"<<endl;
cout<<"현재속도: "<<car.curSpeed<<"km/s"<<endl<<endl;
}
//구조체에 삽입된 이후의 함수
void ShowCarState()
{
cout<<"소유자ID: "<<car.gamerID<<endl;
cout<<"연료량: "<<car.fuelGauge<<"%"<<endl;
cout<<"현재속도: "<<car.curSpeed<<"km/s"<<endl<<endl;
}
- 연산의 대상에 대한 정보가 불필요한 이유는 함수가 구조체 내에 삽입되면서 구조체 내에 선언된 변수에 직접 접근이 가능해 졌기 때문입니다.
// choices.cpp -- 배열 변형
#include <iostream>
using namespace std;
#define ID_LEN 20
#define MAX_SPD 200
#define FUEL_STEP 2
#define ACC_STEP 10
#define BRK_STEP 10
struct Car
{
char gameID[ID_LEN]; //소유자 ID
int fuelGauge; //연료량
int curSpeed; //현재속도
void ShowCarState()
{
cout<<"소유자ID: "<<gameID<<endl;
cout<<"연료량: "<<fuelGauge<<"%"<<endl;
cout<<"현재속도: "<<curSpeed<<"km/s"<<endl<<endl;
}
void Accel()
{
if(fuelGauge<=0)
return;
else
fuelGauge-=FUEL_STEP;
if(curSpeed+ACC_STEP>=MAX_SPD)
{
curSpeed=MAX_SPD;
return;
}
curSpeed+=ACC_STEP;
}
void Break()
{
if(curSpeed<BRK_STEP)
{
curSpeed=0;
return;
}
curSpeed-=BRK_STEP;
}
};
int main(void)
{
Car run99={"run99", 100, 0};
run99.Accel();
run99.Accel();
run99.ShowCarState();
run99.Break();
run99.ShowCarState();
Car sped77={"sped77", 100, 0};
sped77.Accel();
sped77.Break();
sped77.ShowCarState();
return 0;
}
int main()
{
return 0;
}
<출력결과>
소유자ID: run99
연료량: 96%
현재속도: 20km/s
소유자ID: run99
연료량: 96%
현재속도: 10km/s
소유자ID: sped77
연료량: 98%
현재속도: 0km/s
클래스란?
클래스는 데이터(변수)와 함수(메소드)를 묶어서 하나의 단위로 만든 사용자 정의 데이터 타입입니다.
클래스로 할수 있는 것?
- 재사용성: 한 번 만든 클래스는 여러 곳에서 재사용할 수 있어 코드의 중복을 줄이고 유지 보수를 쉽게 만들어 줍니다. 마치 레고 블록을 여러 번 사용해서 다양한 모양을 만드는 것처럼말입니다.
- 캡슐화: 데이터와 함수를 하나로 묶어 외부에서 함부로 접근하지 못하게 보호할 수 있습니다. 마치 레고 블록 안에 중요한 부품을 숨겨 놓는 것처럼 말입니다.
- 추상화: 복잡한 구현 세부 정보를 숨기고 사용자에게 필요한 기능만 제공하여 코드를 더욱 간결하고 이해하기 쉽게 만들어 줍니다. 마치 레고 블록의 겉모습만 보고도 어떤 기능을 하는지 알 수 있는 것처럼말입니다
- 상속: 기존 클래스의 기능을 물려받아 새로운 클래스를 만들 수 있어 코드의 재사용성을 더욱 높여 줍니다. 마치 레고 블록을 쌓아서 더 큰 구조물을 만드는 것처럼말입니다.
- 다형성: 같은 이름의 함수를 다른 방식으로 동작하게 만들어 코드의 유연성을 높여 줍니다. 마치 레고 블록의 색깔을 바꿔서 다른 느낌을 주는 것처럼 말입니다.
클래스의 기본 개념 이해: C++ 세상의 설계도
클래스는 마치 건물을 짓기 위한 설계도와 같습니다. 설계도에는 건물의 구조, 방의 배치, 사용될 재료 등 건물에 대한 모든 정보가 담겨 있죠. C++에서 클래스도 마찬가지로, 특정 객체의 속성(데이터)과 동작(함수)에 대한 정보를 담고 있습니다.
클래스의 구성 요소:
- 멤버 변수: 객체의 속성을 나타내는 변수입니다. 예를 들어, '사람' 클래스라면 이름, 나이, 키 등이 멤버 변수가 될 수 있습니다.
- 멤버 함수: 객체의 동작을 나타내는 함수입니다. 예를 들어, '사람' 클래스라면 걷다, 말하다, 먹다 등이 멤버 함수가 될 수 있습니다.
객체:
클래스는 객체를 생성하기 위한 틀입니다. 객체는 클래스를 실제로 구현한 인스턴스라고 할 수 있습니다. 예를 들어, '사람' 클래스를 통해 '철수'라는 객체를 생성할 수 있습니다. 철수는 사람 클래스의 멤버 변수(이름, 나이, 키)와 멤버 함수(걷다, 말하다, 먹다)를 가지게 됩니다.
접근 제어 지시자 탐구: 클래스의 비밀번호
클래스의 멤버 변수와 멤버 함수는 모두에게 공개되는 것은 아닙니다. 마치 집에 비밀번호를 설정하여 외부인의 출입을 통제하는 것처럼, C++ 클래스도 접근 제어 지시자를 통해 멤버에 대한 접근을 제한할 수 있습니다.
접근 제어 지시자의 종류:
- public: 누구나 접근 가능합니다. 마치 집의 현관문처럼 열려 있는 공간입니다.
- private: 클래스 내부에서만 접근 가능합니다. 마치 집의 침실처럼 개인적인 공간입니다.
- protected: 클래스 내부와 상속받은 자식 클래스에서만 접근 가능합니다. 마치 집의 가족 구성원만 들어갈 수 있는 공간입니다.
캡슐화:
접근 제어 지시자를 사용하여 데이터와 함수를 캡슐화하면 외부에서 함부로 접근하지 못하게 보호할 수 있습니다. 이는 데이터의 무결성을 유지하고 코드의 안정성을 높이는 데 중요한 역할을 합니다. 마치 집에 귀중품을 보관하는 금고처럼, 중요한 데이터를 안전하게 보호하는 것입니다.
생성자와 소멸자 탐구: 객체의 탄생과 죽음
생성자와 소멸자는 객체의 생애 주기에서 중요한 역할을 담당합니다. 마치 사람이 태어나고 죽는 것처럼, 객체도 생성되고 소멸되는 과정을 거치는데, 이때 생성자와 소멸자가 자동으로 호출되어 객체의 초기화와 정리를 담당합니다.
생성자:
- 객체가 생성될 때 자동으로 호출되는 특별한 멤버 함수입니다.
- 객체의 멤버 변수를 초기화하는 데 사용됩니다.
- 생성자는 클래스 이름과 동일하며 반환 값이 없습니다.
- 여러 개의 생성자를 오버로딩하여 다양한 방식으로 객체를 초기화할 수 있습니다.
소멸자:
- 객체가 소멸될 때 자동으로 호출되는 특별한 멤버 함수입니다.
- 객체가 사용하던 자원을 해제하는 데 사용됩니다.
- 소멸자는 클래스 이름 앞에 ~를 붙여 표시하며 반환 값이 없습니다.
- 소멸자는 오버로딩할 수 없습니다.
상속과 다형성 탐구: 클래스의 진화와 변신
상속은 기존 클래스의 기능을 물려받아 새로운 클래스를 만드는 강력한 기능입니다. 마치 부모의 유전 정보를 물려받아 자식이 태어나는 것처럼, 기존 클래스(부모 클래스)의 멤버 변수와 멤버 함수를 물려받아 새로운 클래스(자식 클래스)를 만들 수 있습니다.
상속의 장점:
- 코드 재사용성 증가: 기존 클래스의 기능을 재사용하여 새로운 클래스를 만들 수 있어 코드의 중복을 줄이고 개발 시간을 단축할 수 있습니다.
- 유지 보수 용이성: 기존 클래스를 수정하면 상속받은 모든 자식 클래스에도 변경 사항이 자동으로 적용되어 유지 보수가 편리해집니다.
- 확장성: 기존 클래스를 확장하여 새로운 기능을 추가하거나 기존 기능을 변경할 수 있어 코드의 확장성을 높일 수 있습니다.
다형성:
다형성은 같은 이름의 함수를 다른 방식으로 동작하게 만드는 기능입니다. 마치 카멜레온이 주변 환경에 따라 색깔을 바꾸는 것처럼, 객체의 타입에 따라 같은 이름의 함수가 다른 동작을 수행할 수 있습니다. 다형성은 코드의 유연성과 재사용성을 높이는 데 중요한 역할을 합니다.
클래스 코드 예제 분석
클래스 선언
#include <iostream> // 표준 입출력 라이브러리 포함
#include <cstring> // 문자열 처리 함수(strcpy) 사용을 위한 라이브러리 포함
using namespace std; // std 네임스페이스 사용 (cout, endl 등을 간편하게 사용 가능)
// CAR_CONST라는 이름 공간 정의: 자동차 관련 상수들을 묶어 관리
namespace CAR_CONST
{
// enum을 이용하여 자동차 관련 상수 정의
enum
{
ID_LEN = 20, // 사용자 ID 최대 길이
MAX_SPD = 200, // 최대 속도
FUEL_STEP = 2, // 가속 시 연료 소모량
ACC_STEP = 10, // 가속 시 증가 속도
BRK_STEP = 10 // 브레이크 시 감소 속도
};
}
// Car 클래스 정의: 자동차 객체를 나타내는 틀
class Car
{
private: // private 멤버 변수: 클래스 외부에서 직접 접근 불가
char gamerID[CAR_CONST::ID_LEN]; // 소유자 ID 저장 (최대 길이 20)
int fuelGauge; // 연료량 (%)
int curSpeed; // 현재 속도 (km/s)
public: // public 멤버 함수: 클래스 외부에서 접근 가능
void InintMembers(char* ID, int fuel); // 멤버 변수 초기화 함수
void ShowCarstate(); // 자동차 상태 출력 함수
void Accel(); // 가속 함수
void Break(); // 감속 함수
};
// Car 클래스 멤버 함수 정의: 실제 함수 구현
// 멤버 변수 초기화 함수
void Car::InintMembers(char* ID, int fuel)
{
strcpy(gamerID, ID); // 사용자 ID 복사
fuelGauge = fuel; // 연료량 설정
curSpeed = 0; // 초기 속도 0으로 설정
}
// 자동차 상태 출력 함수
void Car::ShowCarstate()
{
cout << "소유자ID: " << gamerID << endl;
cout << "연료양: " << fuelGauge << "%" << endl;
cout << "현재속도: " << curSpeed << "km/s" << endl << endl;
}
// 가속 함수
void Car::Accel()
{
if (fuelGauge <= 0) // 연료가 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()
{
// 현재 속도가 감속 단계보다 작으면 0으로 설정
if (curSpeed < CAR_CONST::BRK_STEP)
{
curSpeed = 0;
return;
}
curSpeed -= CAR_CONST::BRK_STEP; // 속도 감소
}
// 메인 함수: 프로그램 시작점
int main(void)
{
Car run99; // Car 객체 생성
run99.InintMembers("run99", 100); // 멤버 변수 초기화
run99.Accel(); // 가속
run99.Accel(); // 가속
run99.Accel(); // 가속
run99.ShowCarstate(); // 자동차 상태 출력
run99.Break(); // 감속
run99.ShowCarstate(); // 자동차 상태 출력
return 0; // 프로그램 종료
}
<출력문>
소유자ID: run99
연료양: 94%
현재속도: 30km/s
소유자ID: run99
연료양: 94%
현재속도: 20km/
클래스의 활용
#include <iostream> // 표준 입출력 라이브러리 포함
using namespace std; // std 네임스페이스 사용 선언
// Calculator 클래스 선언
class Calculator
{
private:
// 사칙연산 호출 횟수를 저장할 변수들 선언
int numOfAdd; // 덧셈 호출 횟수
int numOfMin; // 뺄셈 호출 횟수
int numOfMul; // 곱셈 호출 횟수
int numOfDiv; // 나눗셈 호출 횟수
public:
// 멤버 함수 선언
void Init(); // 모든 연산 횟수를 0으로 초기화하는 함수
double Add(double num1, double num2); // 덧셈 연산 함수
double Min(double num1, double num2); // 뺄셈 연산 함수
double Mul(double num1, double num2); // 곱셈 연산 함수
double Div(double num1, double num2); // 나눗셈 연산 함수
void showOpcount(); // 연산 횟수를 출력하는 함수
};
// 멤버 함수 정의
void Calculator::Init()
{
// 연산 횟수를 0으로 초기화
numOfAdd = 0;
numOfMin = 0;
numOfMul = 0;
numOfDiv = 0;
}
double Calculator::Add(double num1, double num2)
{
// 덧셈 수행 후 호출 횟수 증가
numOfAdd++;
return num1 + num2;
}
double Calculator::Min(double num1, double num2)
{
// 뺄셈 수행 후 호출 횟수 증가
numOfMin++;
return num1 - num2;
}
double Calculator::Mul(double num1, double num2)
{
// 곱셈 수행 후 호출 횟수 증가
numOfMul++;
return num1 * num2;
}
double Calculator::Div(double num1, double num2)
{
// 나눗셈 수행 후 호출 횟수 증가
numOfDiv++;
return num1 / num2;
}
void Calculator::showOpcount()
{
// 각 연산 호출 횟수 출력
cout << "덧셈: " << numOfAdd << ' '; // 덧셈 호출 횟수
cout << "뺄셈: " << numOfMin << ' '; // 뺄셈 호출 횟수
cout << "곱셈: " << numOfMul << ' '; // 곱셈 호출 횟수
cout << "나눗셈: " << numOfDiv << ' '; // 나눗셈 호출 횟수
}
// 메인 함수
int main()
{
Calculator cal; // Calculator 객체 생성
cal.Init(); // 연산 횟수를 초기화
// 각 연산 수행 및 결과 출력
cout << "3.2 + 2.4 = " << cal.Add(3.2, 2.4) << endl; // 덧셈 수행
cout << "3.5 / 1.7 = " << cal.Div(3.5, 1.7) << endl; // 나눗셈 수행
cout << "2.2 - 1.5 = " << cal.Min(2.2, 1.5) << endl; // 뺄셈 수행
cout << "4.9 * 1.2 = " << cal.Mul(4.9, 1.2) << endl; // 곱셈 수행
// 연산 횟수 출력
cal.showOpcount();
return 0; // 프로그램 정상 종료
}
<출력문>
3.2+2.4 = 5.6
3.5/1.7 = 2.05882
2.2-1.5 = 0.7
4.9*1.2 = 5.88
덧셈: 1 뺄셈: 1 곱셈: 1 나눗셈: 1
'C++' 카테고리의 다른 글
' : '과 ' :: '의 차이점 (0) | 2024.09.26 |
---|---|
c++클래스(2) (0) | 2024.09.25 |
c++ 참조 (0) | 2024.09.25 |
vector와 array (0) | 2024.09.25 |
C++ 첫 걸음 (3) | 2024.09.24 |
댓글