•
객체 지향 프로그래밍
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++
복사