제4장 클래스와 객체 객체 지향 기법을 이해한다. 클래스를 작성할 수 있다. 클래스에서 객체를 생성할 수 있다. 생성자를 이용하여 객체를 초기화할 수 있다. 접근자와 설정자를 사용할 수 있다.
이번 장에서 만들어볼 프로그램
객체지향이란? 객체 지향 프로그래밍(OOP: object-oriented programming)은 우리가 살고 있는 실제 세계가 객체 (object)들로 구성되어 있는 것과 비슷하게, 소프트웨어도 객체로 구성하는 방법이다.
객체와 메시지 객체들은 메시지를 주고 받으면서 상호작용한다.
절차 지향과 객체 지향
절차지향 절차 지향 프로그래밍(procedural programming)은 프 로시저(procedure)를 기반으로 하는 프로그래밍 방법이 다. 프로시져는 일반적으로 함수를 의미한다. 절차 지향 프로그래밍에서 전체 프로그램은 함수들의 집 합으로 이루어진다.
절차지향의 문제점
객체지향 프로그래밍
객체의 구성 객체는 상태와 동작을 가지고 있다. 객체의 상태(state)는 객체의 속성이다. 객체의 동작(behavior)은 객체가 취할 수 있는 동작이다.
멤버 변수와 멤버 함수
클래스=객체의 설계도 객체 지향 소프트웨어에서도 같은 객체들이 여러 개 필요 한 경우도 있다. 이러한 객체들은 모두 하나의 설계도로 만들어진다. 바로 이 설계도를 클래스(class)라고 한다.
클래스 작성하기
클래스 작성의 예
접근지정자 private 멤버는 클래스 안에서만 접근(사용)될 수 있다. protected 멤버는 클래스 안과 상속된 클래스에서 접근이 가능하다(상속은 아직 학습하지 않았다). public 멤버는 어디서나 접근이 가능하다.
객체 생성하기
객체의 멤버 접근 멤버에 접근하기 위해서는 도트(.) 연산자를 사용한다.
예제 #include <iostream> using namespace std; class Circle { public: int radius; // 반지름 string color; // 색상 double calcArea() { return 3.14*radius*radius; } }; int main() { Circle obj; obj.radius = 100; obj.color = "blue"; cout << "원의 면적=" << obj.calcArea() << "\n"; return 0;
하나의 클래스로 많은 객체 생성 가능
여러 개의 객체 생성 예제 int main() { Circle pizza1, pizza2; pizza1.radius = 100; pizza1.color = "yellow"; cout << "피자의 면적=" << pizza1.calcArea() << "\n"; pizza2.radius = 200; pizza2.color = "white"; cout << "피자의 면적=" << pizza2.calcArea() << "\n"; return 0; }
각 객체 상태 각 객체의 멤버 변수 값은 서로 다르다.
Lab: 사각형 클래스 아래 클래스를 가지고 하나의 객체를 생성하는 프로그램 을 작성해보자. class Rectangle { public: int width, height; int calcArea() { return width*height; } };
solution #include <iostream> using namespace std; class Rectangle { public: int width, height; int calcArea() { return width*height; } }; int main() { Rectangle obj; obj.width = 3; obj.height = 4; int area = obj.calcArea(); cout << "사각형의 넒이: " << area<<endl; return 0;
Lab: 원 객체 그리기 #include <windows.h> #include <stdio.h> int main() { HDC hdc = GetWindowDC(GetForegroundWindow()); Ellipse(hdc, 100, 100, 180, 180); }
solution #include <iostream> #include <windows.h> using namespace std; class Circle { public: int x, y, radius; // 원의 중심점과 반지름 string color; // 원의 색상 double calcArea() { // 원의 면적을 계산하는 함수 return 3.14*radius*radius; } void draw() { // 원을 화면에 그리는 함수 HDC hdc = GetWindowDC(GetForegroundWindow()); Ellipse(hdc, x - radius, y - radius, x + radius, y + radius); };
Lab: Car 클래스 작성
solution #include <iostream> #include <string> using namespace std; class Car { public: // 멤버 변수 선언 int speed; // 속도 int gear; // 기어 string color; // 색상 // 멤버 함수 선언 void speedUp() { // 속도 증가 멤버 함수 speed += 10; } void speedDown() { // 속도 감소 멤버 함수 speed -= 10; };
solution int main() { Car myCar; myCar.speed = 100; myCar.gear = 3; myCar.color = "red"; myCar.speedUp(); myCar.speedDown(); return 0; }
멤버 함수 중복 정의 #include <iostream> #include <string> using namespace std; class PrintData { public: void print(int i) { cout << i << endl; } void print(double f) { cout << f << endl; } void print(string s = "No Data!") { cout << s << endl; } }; int main() { PrintData obj; obj.print(1); obj.print(3.14); obj.print("C++14 is cool."); obj.print(); return 0; }
실행 결과
클래스의 인터페이스와 구현의 분리 복잡한 클래스인 경우에는 멤버 함수를 클래스 외부에서 정의 복잡한 클래스인 경우에는 멤버 함수를 클래스 외부에서 정의 #include <iostream> using namespace std; class Circle { public: double calcArea(); int radius; // 반지름 string color; // 색상 };
클래스의 인터페이스와 구현의 분리 // 클래스 외부에서 멤버 함수들이 정의된다. double Circle::calcArea() { return 3.14*radius*radius; } int main() { Circle c; c.radius = 10; cout << c.calcArea() << endl; return 0;
이름 공간 이름 공간(name space)는 식별자 (자료형, 함수, 변수 등 의 이름)의 영역 이름 공간은 코드를 논리적 그룹으로 구성하고 특히 코드 에 여러 라이브러리가 포함되어 있을 때 발생할 수 있는 이름 충돌을 방지하는 데 사용된다. using namespace std;
using 문장을 사용하지 않으면 #include <iostream> class Circle { public: double calcArea(); int radius; // 반지름 std::string color; // 색상 }; double Circle::calcArea() { return 3.14*radius*radius; } int main() { Circle c; c.radius = 10; std::cout << c.calcArea() << std::endl; return 0;
클래스의 선언과 클래스의 정의 분리
car.h #include <iostream> #include <string> using namespace std; class Car { int speed; //속도 int gear; //기어 string color; //색상 public: int getSpeed(); void setSpeed(int s); };
car.cpp #include "car.h" int Car::getSpeed() { return speed; } void Car::setSpeed(int s) speed = s;
main.cpp #include "car.h" using namespace std; int main() { Car myCar; myCar.setSpeed(80); cout << "현재 속도는 " << myCar.getSpeed() << endl; return 0; }
객체 지향의 개념들 캡슐화 정보은닉 상속 다형성
캡슐화
정보은닉
상속
다형성
Lab: 원들의 경주 두 대의 원을 생성한 후에 난수를 발생하여 원들을 움직 인다. 원을 화면에 그리는 draw() 함수와 난수를 발생하여 원을 움직이는 함수 move()를 클래스에 추가한다.
solution #include <iostream> #include <windows.h> using namespace std; class Circle { public: void init(int xval, int yval, int r); void draw(); void move(); private: int x, y, radius; }; // 아직 생성자를 학습하지 않았기 때문에 init() 함수 사용 void Circle::init(int xval, int yval, int r) { x = xval; y = yval; radius = r; }
solution void Circle::draw() { HDC hdc = GetWindowDC(GetForegroundWindow()); Ellipse(hdc, x - radius, y - radius, x + radius, y + radius); } void Circle::move() { x += rand() % 50; int main() { Circle c1; Circle c2; c1.init(100, 100, 50); c2.init(100, 200, 40); for (int i = 0; i < 20; i++) { c1.move(); c1.draw(); c2.move(); c2.draw(); Sleep(1000); return 0;
UML 객체 지향 프로그래밍에서도 프로그래머들은 애플리케 이션을 구성하는 클래스들 간의 관계를 그리기 위하여 클 래스 다이어그램(class diagram)을 사용한다. 가장 대표 적인 클래스 다이어그램 표기법은 UML(Unified Modeling Language)이다.
UML
UML
UML의 예
Q & A