[PPP - Ch 9] Class (+ Struct과 비교)
Struct과 Class의 차이?
Default visibility 차이밖에 없는 듯 하다. (Inheritance 차이도 있다는데)
Struct : Public
Class : Private
그래서, struct 에서도 constructor나 멤버 함수들 정의가 얼마든지 가능하다.
stackoverflow.com/questions/8454622/c-private-structures
Q. 그러면 언제 class 쓰고 언제 struct씀?
> OOP 관점에서, 데이터만 존재하는 POD(Plain-Old-Date)는 struct을 쓰고, 여러 메소드 및 constructor 등이 필요한 경우엔 class 쓰는게 깔끔.
stackoverflow.com/questions/54585/when-should-you-use-a-class-vs-a-struct-in-c
직관적으로,
데이터만 저장한다 (POD) - struct
복잡한 메소드를 가지고 자신만의 state를 관리하는 객체를 정의하고 싶다 - class
const 멤버 함수
jeunjeun.tistory.com/43?category=631384
Ch9 Drill 최종본 (Class 구현 연습)
enum class Month {
Jan = 1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
};
Month int_to_month(int x) {
if (x<int(Month::Jan) || int(Month::Dec) < x) error("bad month");
return Month(x);
}
class Date {
int y, d;
Month m;
public:
Date(int y, Month m, int d); // check for valid date and initialize
Date();
void add_day(int n); // increase the Date by n days
void add_month(int n); // increase the Date by n days
void add_year(int n); // increase the Date by n days
int day() const { return d; }
Month month() const { return m; }
int year() const { return y; }
};
const Date& default_date() {
static const Date default_date{ 1978, Month::Jun, 25 };
return default_date;
}
bool is_valid(int y, Month m, int d) {
if (!(1800 < y && y < 2999))
throw exception("Invalid year");
else if (!(Month::Jan <= m && m <= Month::Dec))
throw exception("Invalid month");
else if (!(0 < d && d < 32))
throw exception("Invalid day");
}
Date::Date(int yy, Month mm, int dd)
: y(yy), m(mm), d(dd) {
is_valid(yy, mm, dd);
}
Date::Date() {
Date def = default_date();
y = def.year();
m = def.month();
d = def.day();
}
void Date::add_year(int n)
{
if (n < 0)
return;
y += n;
}
void Date::add_month(int n)
{
if (n < 0)
return;
int month_int = int(m);
month_int += n;
if (month_int > 12) {
y += month_int / 12;
month_int %= 12;
}
m = int_to_month(month_int);
}
void Date::add_day(int n)
{
if (n < 0)
return;
int month_int = int(m);
d += n;
if (d > 31) {
//month_int += d / 31;
this->add_month(d / 31);
d %= 31;
}
/*
if (month_int > 12) {
y += month_int / 12;
month_int %= 12;
}
m = int_to_month(month_int);
*/
}
ostream& operator<< (ostream& os, Date& dd) {
os << "{ "
<< dd.year() << ", "
<< static_cast<int>(dd.month()) << ", "
<< dd.day() << " }";
return os;
}
int main() {
try {
Date today{ 1978, Month::Jun, 25 };
Date tomorrow = today; // copy
tomorrow.add_day(1);
cout << today << "\n" << tomorrow << "\n\n";
tomorrow.add_day(15);
cout << tomorrow << "\n\n";
tomorrow.add_day(372); // add a year
cout << tomorrow << "\n\n";
// tomorrow.m = 100; // Invalid!!
// cout << tomorrow << "\n";
Date test{ 2020, Month::Mar, 50 };
cout << test;
}
catch (exception& e) {
cerr << "error: " << e.what() << '\n';
}
}
Ch9 Exercise 5~ Book class
문제를 풀기 위해 필요한 여러 객체들을 모듈화해서 헤더파일로 나눠봄.
종류와 관계는 다음과 같다.
Ch9_drill5.h : class Date, enum class Month
Ch9_exercise_Book.h : class Book
Ch9_exercises.h : 예제들 풀이 모아둔 헤더
main.cpp : Ch9_exerises.h를 include 하여 각 풀이 돌려보는 메인 파일
Q. 헤더가 필요한 이유? 구현부 (정의; Definition)를 헤더에 작성하면 안되나? (이미 Ch9_exercises.h에서 실컷 했는데)
* 헤더 파일 중복 include 방지 (#pragma once, #ifndef #define #endif)
header의 함수 전방 선언에 default parameter 설정해주면,
구현부의 함수 정의에서는 default parameter 중복해서 넣어주면 안됨.
enum class를 switch 구문에 쓸 수 있다.
그리고 앞전 강의에서 배운 enum문(열거형) , enum class문(영역 제한 열거형) 열거체들은
상수에 이름을 부여해주는 기능입니다!
그래서 switch 문과 enum문은 함께 응용되어 많이 사용됩니다.
<활용>
이렇게 Colors 라는 이름의 enum 문을 작성하면
상수 0 은 BLACK 이라는 이름을 갖게 되고,
상수 1 은 WHITE 이라는 이름을 갖게 되고,
상수2 는 RED 라는 이름을 갖게 되고, (3 == GREEN, 4 ==BLUE)
cin, enum class, switch를 활용하여 이런 재밌는 코드를 작성하는 것이 가능해지게 됩니다!
사용자가 0을 입력하면 Black, 1을 입력하면 white 를,
사용자가 입력한 값이 case에서 찾을 수 없을 경우 '잘못 입력했다'고 콘솔창에 출력하는 코드입니다
빨간 밑줄은 명시적 형변환을 해주고 있는 모습입니다
형변환을 안해주면 아래와 같은 오류가 발생하기 때문입니다
'case에 있는 상수식이 enum class Colors 타입인데 왜 조건식에는 int 타입을 넣는거얏!' 하고 화내는 모습인듯 합니다ㅋㅋㅋ
그래서 switch 조건식도 Colors 사용자정의타입 으로 명시적 형변환을 하여 타입을 맞춰주었습니다.
그리고 switch 문이 꽤 길어보이고 복잡해 보이지만,
비쥬얼스튜디오에는 switch 문을 프로그래머가 더 빨리, 더 쉽게 입력할 수 있도록 도와주는
자동완성 기능이 존재합니다!
< switch문 자동완성 >
'switch' 입력 → (tab) → enum class 이름 (위 예제에서는 'Colors')입력 → 다른곳 클릭
중간에 스페이스바나 다른 입력은 하지 않습니다.
( 참고 : https://ntbda.tistory.com/16 )
(참고2 : https://helloacm.com/code-snippet-auto-complete-on-switch-statement-using-enum-in-visual-studio/)
꽤 재미있는 기능이므로 여러가지 enum class를 활용하여 switch 문을 만들어보세요!
Ch9 Ex9
헤더를 나눠서 여러 class를 엮어서 구현.
파일 구조는 아래와 같이 됨.
Library를 만들다 보니, 효율적인 시스템 설계에 대해 고민해보게 됨.
Data consistency를 지키기 위해, Library를 DB로 구현해서 그 속에만 Book, Patron 정보 저장.
이후, 회원이 책을 빌리거나 (check_out) 반납할때 (check_in), 입력하는 정보를 가지고 DB에서 해당하는 책과 회원을 찾은 다음 연산을 실행하는 방법이 가장 깔끔할 듯.
(물론 어떤 정보를 입력받을 것인지, 또 Library가 지원하는 기타 기능들은 무엇이 있는지 등은 추가로 생각해봐야할 문제)
'<기타 공부> > [기술서적]' 카테고리의 다른 글
[PPP - Ch 8] Functions - Drills (0) | 2020.12.05 |
---|