🥞 BE
home

6. 클래스와 생성자 (2)

Date
2022/05/17
Category
Programming Language
Tag
C++
Detail
객체 지향 프로그래밍
1.
인터페이스 파일 - 클래스 정의(데이터 멤버 선언과 멤버 함수 선언)가 포함된 파일 ex) circle.h
2.
구현 파일 - 멤버 함수 정의가 포함된 파일 ex) circle.cpp
3.
애플리케이션 파일 - 객체를 인스턴스화하고 활용하는 main 함수가 포함된 파일 ex) app.cpp
이를 분할 컴파일이라고 부름.
인터페이스 파일 (circle.h)
#ifndef CIRCLE_H #define CIRCLE_H #include<iostream> #include<cassert> #include"circle.h" using namespace std; class Circle { private: double radius; public: Circle(double radius); Circle(); Circle(const Circle& circle); ~Circle(); void setRadius(double radius); double getRadius()const; double getArea()const; double getPerimeter()const; }; #endif
C++
복사
구현 파일 (circle.cpp)
#include "circle.h" // 매개변수 생성자 Circle::Circle(double rds) :radius(rds) { if (radius < 0.0) { assert(false); } } // 기본 생성자 Circle::Circle() :radius(0.0) { } // 복사 생성자 Circle::Circle(const Circle& circle) : radius(circle.radius) { } // 소멸자 Circle::~Circle() { } // 설정자 함수 void Circle::setRadius(double value) { radius = value; if (radius < 0.0) { assert(false); } } // 접근자 함수 double Circle::getRadius()const { return radius; } double Circle::getArea()const { const double PI = 3.14; return(PI * radius * radius); } double Circle::getPerimeter()const { const double PI = 3.14; return (2 * PI * radius); }
C++
복사
애플리케이션 파일 (app.cpp)
#include "circle.h" int main() { // 매개변수 생성자 인스턴스 Circle circle1(5.2); cout << "Radius: " << circle1.getRadius() << endl; cout << "Area: " << circle1.getArea() << endl; cout << "Perimeter: " << circle1.getPerimeter() << endl; cout << endl; // 복사 생성자 인스턴스 Circle circle2(circle1); cout << "Radius: " << circle2.getRadius() << endl; cout << "Area: " << circle2.getArea() << endl; cout << "Perimeter: " << circle2.getPerimeter() << endl; cout << endl; // 일반 생성자 인스턴스 Circle circle3; cout << "Radius: " << circle3.getRadius() << endl; cout << "Area: " << circle3.getArea() << endl; cout << "Perimeter: " << circle3.getPerimeter() << endl; cout << endl; return 0; }
C++
복사
캡슐화
클래스 설계클래스 사용으로 구분됨.
클래스 설계
설계자가 인터페이스 파일, 구현 파일 만듦. 인터페이스 파일만 공개함.
구현 파일의 경우는 컴파일한 것만 공개하고 소스 코드는 비공개로 유지.
클래스 사용
사용자는 인터페이스 파일의 복사본컴파일된 구현 파일을 받음.
이를 애플리케이션 파일에서 읽어 들이고 컴파일.
최종적으로 모든 파일을 연결해서 실행 파일을 생성.
Fraction 클래스
C++에는 분수를 나타내는 내장 자료형이 없음.
따라서 분자를 나타내는 값(numer: numerator)과 분모를 나타내는 값(denom: denominator)의
int 자료형 2개를 활용해서 새로운 자료형 분수(Fraction)를 만들어야 함.
— 불변 속성
2/0 : 불능
0/0 : 부정
위의 경우 프로그램 종료.
gcd 함수는 분모와 분자의 최대 공약수를 찾음.
normalize 함수는 gcd 함수를 활용해서 위의 불변 속성을 처리.
인터페이스 파일 (fraction.h)
#ifndef FRACTION_H #define FRACTION_H #include<iostream> using namespace std; class Fraction { // 데이터 멤버 private: int numer; // numerator(분자) int denom; // denominator(분모) public: // 생성자 Fraction(int num, int den); Fraction(); Fraction(const Fraction& fract); ~Fraction(); // 접근자 함수 int getNumer()const; int getDenom()const; void print()const; // 설정자 함수 void setNumer(int num); void setDenom(int den); private: void normalize(); int gcd(int n, int m); }; #endif // !FRACTION_H
C++
복사
구현 파일 (fraction.cpp)
분모가 음수일 때는 분자와 분모의 부호를 변경.
따라서 분모는 양수가 되고, 분자가 음수.
최대 공약수 함수를 사용해서 분자와 분모의 최대 공약수를 찾은 뒤, 분자와 분모를 나눔.
gcd는 절댓값 사용.
#include"fraction.h" #include<iostream> #include<cmath> #include<cassert> using namespace std; Fraction::Fraction(int num, int den = 1) :numer(num), denom(den) { normalize(); } Fraction::Fraction() : numer(0), denom(1) { } Fraction::Fraction(const Fraction& fract) : numer(fract.numer), denom(fract.denom) { } Fraction::~Fraction() { } int Fraction::getNumer()const { return numer; } int Fraction::getDenom()const { return denom; } void Fraction::print()const { cout << numer << "/" << denom << endl; } void Fraction::setNumer(int num) { numer = num; normalize(); } void Fraction::setDenom(int den) { denom = den; normalize(); } void Fraction::normalize() { if (denom == 0) { cout << "Invalid denominaton. Need to quit." << endl; assert(false); } if (denom < 0) { denom = -denom; numer = -numer; } int divisor = gcd(abs(numer), abs(denom)); numer = numer / divisor; denom = denom / divisor; } int Fraction::gcd(int n, int m) { int gcd = 1; for (int k = 1; k <= n && k <= m; k++) { if (n % k == 0 && m % k == 0) { gcd = k; } } return gcd; }
C++
복사
애플케이션 파일 (app.cpp)
#include"fraction.h" #include<iostream> using namespace std; int main() { Fraction fract1; Fraction fract2(14, 21); Fraction fract3(11, -8); Fraction fract4(fract3); cout << "Printing four fractions after constructed: " << endl; cout << "fract1: "; fract1.print(); cout << "fract2: "; fract2.print(); cout << "fract3: "; fract3.print(); cout << "fract4: "; fract4.print(); cout << endl; cout << "Changing the first two fractions and printing them: " << endl; fract1.setNumer(4); cout << "fract1: "; fract1.print(); fract2.setDenom(-5); cout << "fract2: "; fract2.print(); cout << endl; cout << "Testing the changes in two fractions: " << endl; cout << "fract1 numerator: " << fract1.getNumer() << endl; cout << "fract2 numerator: " << fract2.getDenom() << endl; return 0; }
C++
복사
Time 클래스
실제 시간처럼 hours, minutes, seconds라는 3가지 데이터 멤버를 가짐.
hours, minutes, seconds를 추출하는 3가지 접근자 함수를 만들고 설정자 함수로 시간을 1초만큼 증가시키는 tick 함수를 생성.
— 불변 속성
음수 시간은 존재하지 않기 때문에 모든 데이터 멤버는 음수가 될 수 없음. 입력 시 프로그램 중지.
hours는 0~23, minutes는 0~59, seconds는 0~59 사이어야 하며 이러한 범위를 유지하려면 몫과 나머지를 사용.
또한 seconds가 59보다 커지면 minutes를 1만큼 올리고, minutes가 59보다 커지면 hours를 1만큼 증가.
인터페이스 파일 (time.h)
#ifndef TIME_H #define TIME_H #include<iostream> using namespace std; class Time { private: int hours; int minutes; int seconds; public: Time(int hours, int minutes, int seconds); Time(); ~Time(); void print()const; void tick(); private: void normalize(); }; #endif // !TIME_H
C++
복사
구현 파일 (time.cpp)
#include"time.h" #include<cmath> #include<cassert> Time::Time(int hr, int mi, int se):hours(hr), minutes(mi), seconds(se) { normalize(); } Time::Time() : hours(0), minutes(0), seconds(0) { } Time::~Time() { } void Time::print()const { cout << hours << ":" << minutes << ":" << seconds << endl; } void Time::tick() { seconds++; normalize(); } void Time::normalize() { if ((hours < 0) || (minutes < 0) || (seconds < 0)) { cout << "Data are not valid. Need to quit!" << endl; assert(false); } if (seconds > 59) { int temp = seconds / 60; seconds = seconds % 60; minutes = minutes + temp; } if (minutes > 59) { int temp = minutes / 60; minutes = minutes % 60; hours = hours + temp; } if (hours > 23) { hours = hours % 24; } }
C++
복사
애플리케이션 파일 (app.cpp)
#include"time.h" int main() { Time time(4, 5, 27); cout << "Original time: "; time.print(); for (int i = 0; i < 143500; i++) { time.tick(); } cout << "Time after 143500 ticks "; time.print(); return 0; }
C++
복사