차이
문서의 선택한 두 판 사이의 차이를 보여줍니다.
양쪽 이전 판 이전 판 | |||
activity:public:2021:cpp:210720 [2021/07/21 03:45:36] – [예제] yhy01625 | activity:public:2021:cpp:210720 [2021/07/23 22:05:46] (현재) – [C++ 스터디 #11: 클래스(1)] bkparks12 | ||
---|---|---|---|
줄 1: | 줄 1: | ||
+ | ======C++ 스터디 #11: 클래스(1)====== | ||
+ | | 시간 | 2021년 7월 20일 화요일 20:00 ~ 22:00 | | ||
+ | | 장소 | ZOOM | | ||
+ | | 참가자 | - | | ||
+ | |||
+ | {{youtube> | ||
+ | =====1. 객체 지향 프로그래밍===== | ||
+ | ====1.1. 개요==== | ||
+ | 현재 많이 사용되는 프로그래밍 기법은 절차 지향 프로그래밍과 객체 지향 프로그래밍으로 나눌 수 있습니다. | ||
+ | |||
+ | \\ | ||
+ | {{: | ||
+ | {{: | ||
+ | |||
+ | \\ | ||
+ | **절차 지향 프로그래밍(procedural programming)**에서 전체 프로그램은 함수들의 집합으로 이루어집니다. 이런 설계 방법은 하향식 설계라고도 불립니다.\\ | ||
+ | 하지만 데이터가 함수와 분리되기 때문에 프로그래머들은 함수 작성에만 신경을 쓰게 되는 단점이 있습니다.\\ | ||
+ | \\ | ||
+ | 이런 문제점을 해결하기 위해 등장한 것이 **객체 지향 프로그래밍(object-oriented programming)**입니다.\\ | ||
+ | 객체 지향 프로그래밍은 데이터와 함수를 하나의 덩어리인 객체로 묶어서 생각하는 방법입니다.\\ | ||
+ | 이렇게 묶는 것을 **캡슐화(encapsulation)**라고 부릅니다. | ||
+ | |||
+ | |||
+ | ====1.2. 객체의 구성==== | ||
+ | 객체는 상태와 동작을 가지고 있습니다. 객체의 **상태(state)**는 객체의 속성입니다.\\ | ||
+ | 예를 들어 자동차 객체의 경우 속성은 차종, 색상, 기어, 속도, 배기량, 주행 거리, 연비 등을 생각할 수 있습니다.\\ | ||
+ | 객체의 **동작(behavior)**은 객체가 취할 수 있는 동작입니다.\\ | ||
+ | 자동차를 예로 들면 출발하기, | ||
+ | |||
+ | 객체의 상태와 동작은 프로그램에서 변수와 함수로 표현할 수 있습니다.\\ | ||
+ | 즉 객체는 변수와 함수로 이루어져 있는 코드의 묶음이라 할 수 있습니다. | ||
+ | \\ | ||
+ | ***멤버 변수 :** 객체 안의 변수에는 객체의 상태를 저장합니다. 객체 안에 포함된 변수를 일반적인 변수와 구별하기 위하여 특별히 **멤버 변수 또는 필드(field)**라고 합니다. | ||
+ | ***멤버 함수 :** 객체 안의 함수는 특정한 동작을 수행합니다. 일반적인 함수와 구별하기 위해서 객체 안의 함수를 **멤버 함수 또는 메소드(method)**라고 합니다. | ||
+ | |||
+ | ====1.3. 캡슐화==== | ||
+ | |||
+ | 새로운 프로그램을 개발할 때 기존에 작성된 코드를 재사용할 수 있다면 편리할 것입니다.\\ | ||
+ | 관련 데이터와 알고리즘이 하나의 묶음으로 정리되어 있고, 객체 지향 프로그래밍에서는 이를 캡슐화라고 합니다.\\ | ||
+ | 객체가 하나의 캡슐에 해당하고, | ||
+ | \\ | ||
+ | **캡슐화의 목적 1. 관련 데이터와 알고리즘 묶기**\\ | ||
+ | 서로 관련되어 있는 데이터와 알고리즘이 묶여 있으면 사용하기 매우 편리합니다.\\ | ||
+ | 캡슐로 된 약처럼, 캡슐로 감싸져 있지 않으면 안의 내용물들이 흩어지게 되고 복용이 힘들 것입니다.\\ | ||
+ | \\ | ||
+ | **캡슐화의 목적 2. 정보 은닉: 접근 가능한 것과 접근해서는 안되는 것 분리**\\ | ||
+ | 외부에서 객체의 세부 사항을 너무 많이 알아도 문제가 될 수 있습니다.\\ | ||
+ | 어떤 사람이 TV 채널을 돌리거나 음량을 바꿀 때 리모콘을 사용하지 않고 내부 회로를 마구 조작하면서 사용하다가, | ||
+ | TV 제조사가 안전하게 TV를 사용할 수 있게 리모콘을 제공한 것처럼, 프로그래밍에서도 객체를 사용할 때 접근 가능한 것과 접근해서는 안되는 것을 분리합니다.\\ | ||
+ | =====2. 클래스===== | ||
+ | |||
+ | ====2.1. 클래스의 역할==== | ||
+ | |||
+ | 자동차 객체의 경우 같은 설계도에 의해 각각의 자동차가 만들어집니다. 객체 지향 소프트웨어에서도 같은 객체들이 여러 개 필요한 경우가 있습니다.\\ | ||
+ | 이러한 객체들은 모두 하나의 설계도로 만들어집니다. 바로 이 설계도를 **클래스(class)**라고 합니다.\\ | ||
+ | 다시 말하면 클래스란 어떤 종류의 모든 객체에게 공통인 멤버 변수와 멤버 함수를 정의하는 형틀 또는 청사진이라고 할 수 있습니다.\\ | ||
+ | 객체 지향 프로그래밍에서는 클래스로부터 만들어지는 객체를 그 클래스의 **인스턴스(instance)**라고 합니다. | ||
+ | |||
+ | 객체가 생성될 때마다 각 객체에 필요한 기억 공간이 할당됩니다. 같은 설계도로 만들어진 자동차라고 해도 각 자동차의 속도, 주행 거리, 기어 등의 상태는 다릅니다.\\ | ||
+ | 따라서 같은 클래스로 만들어진 인스턴스라고 해도 각기 다른 상태 값을 가질 수 있습니다. 따라서 이들 상태 값을 저장할 공간이 객체마다 필요합니다. 즉 객체마다 멤버 변수의 값은 달라집니다. | ||
+ | |||
+ | 멤버 함수의 경우는 약간 다릅니다. 자동차를 예로 들면 전조등을 켜는 방법은 같은 설계도로 만든 자동차이면 모두 동일합니다.\\ | ||
+ | 따라서 객체의 멤버 함수들은 객체마다 저장되는 것이 아니라 하나의 멤버 함수를 공유합니다.\\ | ||
+ | 정리하자면 같은 클래스의 인스턴스들은 멤버 함수는 공유하지만 멤버 변수는 각각 가지고 있다고 말할 수 있습니다. | ||
+ | |||
+ | ====2.2. 클래스 작성==== | ||
+ | 클래스는 다음과 같이 정의됩니다. | ||
+ | |||
+ | class 클래스이름 { | ||
+ | 자료형 멤버변수1; | ||
+ | 자료형 멤버변수2; | ||
+ | | ||
+ | 반환형 멤버함수1(); | ||
+ | 반환형 멤버함수2(); | ||
+ | }; | ||
+ | \\ | ||
+ | 간단한 예시를 작성하면 다음과 같습니다. | ||
+ | <sxh cpp> | ||
+ | class Circle { | ||
+ | public: | ||
+ | int radius; | ||
+ | string color; | ||
+ | | ||
+ | double calcArea() { | ||
+ | return 3.14*radius*radius; | ||
+ | } | ||
+ | }; | ||
+ | </ | ||
+ | 일반적으로 클래스 이름은 명사로 하며, 첫 글자는 대문자로 합니다. 위 예시에서 클래스의 이름은 Circle입니다.\\ | ||
+ | 이어서 등장하는 키워드 public은 외부에서 멤버들을 자유롭게 사용할 수 있음을 의미합니다.\\ | ||
+ | Circle 클래스 안에는 원의 반지름을 나타내는 radius 변수와 원의 색상을 나타내는 color 변수를 선언하였고 멤버 함수로는 원의 반지름을 계산하여 반환하는 calcArea() 함수를 정의했습니다.\\ | ||
+ | 클래스의 정의가 끝나면 반드시 ;을 붙어야 합니다. | ||
+ | |||
+ | ====2.3. 객체 생성==== | ||
+ | 클래스를 선언하였다고 해서 객체가 생성된 것은 아닙니다. 클래스의 정의는 객체를 찍어내는 틀을 만든 것에 불과합니다.\\ | ||
+ | 틀을 사용하여 객체를 생성해야 객체를 사용할 수 있습니다. | ||
+ | Circle obj; | ||
+ | 위의 문장이 실행되면 obj라는 객체가 생성되게 됩니다. 이처럼 실제로 생성된 객체를 클래스의 인스턴스라고 부릅니다.\\ | ||
+ | Circle이라는 클래스 이름은 자료형의 이름으로 생각할 수 있습니다. obj는 객체의 이름이 됩니다. | ||
+ | |||
+ | ====2.4. 객체의 멤버 접근==== | ||
+ | 객체 안에 정의된 멤버 변수와 멤버 함수를 사용하려면 도트(.)연산자를 사용해야 합니다.\\ | ||
+ | 예를 들어 obj 객체의 변수 radius에 값을 대입하려면 다음과 같이 해야 합니다. | ||
+ | obj.radius = 3; | ||
+ | 하나의 클래스에서 많은 객체가 생성될 수 있기 때문에 어떤 객체의 어떤 멤버인지를 적어주는 것입니다. | ||
+ | obj.calcArea(); | ||
+ | 위와 같이 도트 연산자를 이용하여 멤버 함수도 호출할 수 있습니다. | ||
+ | |||
+ | ====2.5. 예제==== | ||
+ | 사각형을 클래스 Rectangle로 표현하세요. width, height를 멤버 변수로 가지고 사각형의 면적을 계산하는 calcArea()를 멤버 함수로 가져야 합니다.\\ | ||
+ | 그리고 클래스 Rectangle로 obj1, obj2라는 이름의 두 개의 객체를 생성하고 각 객체의 면적을 출력하는 프로그램을 작성하세요. | ||
+ | |||
+ | |||
+ | =====3. 멤버 함수 중복 정의===== | ||
+ | <sxh cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | 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!" | ||
+ | }; | ||
+ | |||
+ | int main() { | ||
+ | PrintData obj; | ||
+ | | ||
+ | obj.print(1); | ||
+ | obj.print(3.14); | ||
+ | obj.print(" | ||
+ | obj.print(); | ||
+ | | ||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | 위의 코드에서 멤버 함수 print()는 정수, 실수, 문자열에 대하여 중복 정의되어 있습니다.\\ | ||
+ | 따라서 어떤 자료형의 데이터든지 출력할 수 있습니다. 문자열을 출력하는 print()는 매개 변수가 주어지지 않으면 문자열 "No Data!" | ||
+ | |||
+ | 출력 예시:\\ | ||
+ | {{: | ||
+ | =====4. 클래스의 인터페이스와 구현의 분리===== | ||
+ | 만약 멤버 함수가 매우 복잡해서 100줄이 넘으면 클래스의 정의가 어디서 시작해서 어디서 끝나는지를 분간하기 힘들 것입니다.\\ | ||
+ | 이런 경우에는 클래스 외부에 멤버 함수를 정의해야 합니다.\\ | ||
+ | <sxh cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | using namespace std; | ||
+ | |||
+ | class Circle { | ||
+ | public: | ||
+ | double calcArea(); | ||
+ | | ||
+ | int radius; | ||
+ | string color; | ||
+ | } | ||
+ | |||
+ | double Circle:: | ||
+ | return 3.14*radius*radius; | ||
+ | } | ||
+ | |||
+ | int main() { | ||
+ | Circle obj; | ||
+ | obj.radius = 10; | ||
+ | | ||
+ | cout << obj.calcArea() << endl; | ||
+ | | ||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | 클래스 외부에서 calcArea() 함수를 정의할 때 함수 이름 앞에 클래스 이름인 Circle과 :: | ||
+ | :: | ||
+ | |||
+ | =====5. 생성자===== | ||
+ | ====5.1. 생성자 함수==== | ||
+ | 변수를 사용하기 위해서는 초기화를 해주어야 한다.\\ | ||
+ | 객체도 이와 마찬가지로 생성한 후 초기화를 해야 사용할 수 있다.\\ | ||
+ | C++에서는 초기화를 담당하는 생성자 함수가 존재한다. 이를 사용하면 객체의 생성과 동시에 초기화를 할 수 있다.\\ | ||
+ | \\ | ||
+ | 직사각형을 나타내는 클래스 Rectangle을 다음과 같이 정의하자. | ||
+ | <sxh cpp> | ||
+ | #include < | ||
+ | using namespace std; | ||
+ | |||
+ | class Rectangle { | ||
+ | private: | ||
+ | int width, height; | ||
+ | public: | ||
+ | int calcArea() { | ||
+ | return width * height; | ||
+ | } | ||
+ | }; | ||
+ | </ | ||
+ | \\ | ||
+ | 클래스 Rectangle의 객체를 생성하고 변수에 여러 값들을 저장해보자. | ||
+ | |||
+ | <sxh cpp> | ||
+ | int main() { | ||
+ | Rectangle r; // 객체 r을 생성한다. | ||
+ | |||
+ | r.width = 4; // 객체 r의 너비를 4, 높이를 3으로 설정한다. | ||
+ | r.height = 3; | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | \\ | ||
+ | 하지만 깜빡하고 객체를 초기화하지 않는다면 문제가 발생할 것이다. | ||
+ | |||
+ | <sxh cpp> | ||
+ | int main() { | ||
+ | Rectangle r; | ||
+ | |||
+ | cout << r.calcArea(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | 혹은, 멤버 변수가 private이라면 변수에 직접 접근할 수 없어 아까와 같은 방법으로는 값을 저장할 수 없다.\\ | ||
+ | 이때는 값을 저장할 수 있는 public인 멤버 함수를 만들어 사용해야 한다.\\ | ||
+ | 따라서 객체를 생성할 때 자동으로 객체를 초기화할 수 있다면 매우 편리할 것이다.\\ | ||
+ | 이를 생성자 함수라고 한다. | ||
+ | |||
+ | <sxh cpp> | ||
+ | class Rectangle { | ||
+ | private: | ||
+ | int width, height; | ||
+ | public: | ||
+ | Rectangle(int w, int h) { | ||
+ | width = w; | ||
+ | height = h; | ||
+ | } | ||
+ | int calcArea() { | ||
+ | return width * height; | ||
+ | } | ||
+ | }; | ||
+ | </ | ||
+ | |||
+ | 생성자는 클래스 이름과 똑같은 멤버 함수이고 반환 형식은 따로 존재하지 않는다. | ||
+ | |||
+ | <sxh cpp> | ||
+ | Rectangle a; // 오류! 초기화값 없음 | ||
+ | Rectangle b(4, 3); // OK. 직접 초기화, 예전 방법, 하지만 함수 선언과 혼동할 수 있음 | ||
+ | Rectangle c {4, 3}; // OK. 유니폼 초기화, 최신 방법. | ||
+ | Rectangle d = {4, 3}; // OK. 약간은 간결하지 않음 | ||
+ | </ | ||
+ | |||
+ | 생성자를 사용하는 전체 코드는 이렇다. | ||
+ | |||
+ | <sxh cpp> | ||
+ | #include < | ||
+ | using namespace std; | ||
+ | |||
+ | class Rectangle { | ||
+ | private: | ||
+ | int width, height; | ||
+ | public: | ||
+ | Rectangle(int w, int h) { | ||
+ | width = w; | ||
+ | height = h; | ||
+ | } | ||
+ | int calcArea() { | ||
+ | return width * height; | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | int main() { | ||
+ | Rectangle r {4, 3}; | ||
+ | cout << r.calcArea(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | \\ | ||
+ | ====5.2. 생성자 중복 정의==== | ||
+ | |||
+ | 생성자도 멤버 함수의 일종이라고 생각할 수 있고, 따라서 생성자도 함수 오버로딩처럼 중복 정의가 가능하다. | ||
+ | |||
+ | 다음은 매개 변수가 없는 생성자와 매개 변수가 있는 생성자를 동시에 정의한 것이다. | ||
+ | |||
+ | <sxh cpp> | ||
+ | #include < | ||
+ | using namespace std; | ||
+ | |||
+ | class Rectangle { | ||
+ | private: | ||
+ | int width, height; | ||
+ | public: | ||
+ | Rectangle() { | ||
+ | width = 1; | ||
+ | height = 1; | ||
+ | } | ||
+ | Rectangle(int w, int h) { | ||
+ | width = w; | ||
+ | height = h; | ||
+ | } | ||
+ | int calcArea() { | ||
+ | return width * height; | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | int main() { | ||
+ | Rectangle a; // 매개 변수가 없는 생성자가 호출된다. 너비와 높이가 1로 설정된다. | ||
+ | Rectangle b {4, 3}; // 매개 변수가 있는 생성자가 호출된다. | ||
+ | cout << a.calcArea() << endl; // 1 | ||
+ | cout << b.calcArea(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | 이렇게 매개 변수가 없는 생성자를 기본 생성자라고 한다. 기본 생성자는 객체를 생성할 때 인수를 주지 않으면 자동으로 호출된다.\\ | ||
+ | |||
+ | <color # | ||
+ | </ | ||
+ | |||
+ | <sxh cpp> | ||
+ | Rectangle a; // OK. 기본 생성자가 호출된다. | ||
+ | Rectangle b(); // X. 기본 생성자가 아니다. | ||
+ | </ | ||
+ | \\ | ||
+ | ====예제: 평면 위의 점==== | ||
+ | 2차원 평면 위의 한 점을 나타내는 클래스 Point를 생성자를 포함하여 작성하라.\\ | ||
+ | 멤버 변수는 private으로, | ||
+ | 따로 좌표를 설정하지 않으면 기본 좌표를 (0, 0)으로 설정하라.\\ | ||
+ | 객체의 좌표를 출력하는 멤버 함수는 클래스 외부에 정의하라. | ||
+ | |||
+ | x = 0, y = 0 | ||
+ | x = 2, y = 3 | ||
+ | \\ | ||
+ | 답안 예시 | ||
+ | <sxh cpp> | ||
+ | #include < | ||
+ | using namespace std; | ||
+ | |||
+ | class Point { | ||
+ | private: | ||
+ | int x, y; | ||
+ | |||
+ | public: | ||
+ | Point() { | ||
+ | x = 0; | ||
+ | y = 0; | ||
+ | } | ||
+ | |||
+ | Point(int a, int b) { | ||
+ | x = a; | ||
+ | y = b; | ||
+ | } | ||
+ | |||
+ | void printXY(); | ||
+ | }; | ||
+ | |||
+ | int main() { | ||
+ | Point p; | ||
+ | Point q(2, -3); | ||
+ | |||
+ | p.printXY(); | ||
+ | q.printXY(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | void Point:: | ||
+ | cout << "x = " << x << ", y = " << y << endl; | ||
+ | } | ||
+ | </ | ||
+ | ====5.3. 디폴트 인수를 사용하는 생성자==== | ||
+ | 생성자의 매개변수는 디폴트 값을 가질 수 있다. | ||
+ | |||
+ | <sxh cpp> | ||
+ | #include < | ||
+ | using namespace std; | ||
+ | |||
+ | class Rectangle { | ||
+ | private: | ||
+ | int width, height; | ||
+ | public: | ||
+ | Rectangle(int w = 1, int h = 1) { | ||
+ | width = w; | ||
+ | height = h; | ||
+ | } | ||
+ | int calcArea() { | ||
+ | return width * height; | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | int main() { | ||
+ | Rectangle a; | ||
+ | Rectangle b{4, 3}; | ||
+ | cout << a.calcArea() << endl; // 1 | ||
+ | cout << b.calcArea(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ====5.4. 멤버 초기화 리스트==== | ||
+ | 앞서 클래스 Rectangle의 생성자에서 멤버 변수를 다음과 같이 초기화했다. | ||
+ | |||
+ | <sxh cpp> | ||
+ | class Rectangle { | ||
+ | private: | ||
+ | int width, height; | ||
+ | public: | ||
+ | Rectangle(int w, int h) { | ||
+ | width = w; | ||
+ | height = h; | ||
+ | } | ||
+ | }; | ||
+ | </ | ||
+ | |||
+ | 하지만 이것은 모두 할당이지 초기화를 해준 것이 아니다.\\ | ||
+ | 생성자 함수가 실행될 때 멤버 변수인 width와 height가 생성된 후, 생성자 본문이 실행되어 값이 할당된다.\\ | ||
+ | 이는 유효한 방법이지만 초기화보다 효율적이지 않다.\\ | ||
+ | 게다가 어떤 종류는 선언과 동시에 초기화를 해 주어야 한다. | ||
+ | |||
+ | <sxh cpp> | ||
+ | class Rectangle { | ||
+ | private: | ||
+ | const int width; | ||
+ | int& height; | ||
+ | public: | ||
+ | Rectangle(int w, int& h) { | ||
+ | width = w; // const 변수는 할당할 수 없다. | ||
+ | height = h; // 참조 변수는 선언과 동시에 초기화되어야 한다. | ||
+ | } | ||
+ | }; | ||
+ | </ | ||
+ | |||
+ | 이런 문제를 해결하기 위해 C++에서는 초기화 리스트를 통해 멤버 변수를 초기화할 수 있다. | ||
+ | <sxh cpp> | ||
+ | Rectangle(int w, int h) : width(w), height(h) {} // width를 w로, height를 h로 초기화한다. | ||
+ | </ | ||
+ | |||
+ | 또한, 기본값이 지정되어 있더라도 생성자 멤버 초기화 리스트가 가장 우선시된다. | ||
+ | <sxh cpp> | ||
+ | class Rectangle { | ||
+ | public: | ||
+ | int width = 1; | ||
+ | int height = 1; | ||
+ | Rectangle(int w, int h) : width(w), height(h) {} | ||
+ | }; | ||
+ | |||
+ | int main() { | ||
+ | Rectangle r {2}; // 값을 하나만 전달하면 앞에서부터 차례대로 채운다. | ||
+ | cout << r.width << endl; // 2 | ||
+ | cout << r.height; | ||
+ | </ | ||
+ | \\ | ||
+ | ====예제: 시간==== | ||
+ | 시간을 나타내는 클래스 Time을 작성하라.\\ | ||
+ | 시와 분을 입력받아 시간 객체를 생성하라.\\ | ||
+ | 멤버 초기화 리스트를 이용하여 객체를 초기화하라.\\ | ||
+ | 다음을 생성자 함수에서 수행하라.\\ | ||
+ | * 입력받은 시가 0 이상 24 미만의 정수가 되도록 24를 더하거나 뺄 것\\ | ||
+ | * 입력받은 분이 0 이상 60 미만의 정수가 되도록 60을 더하거나 뺄 것\\ | ||
+ | 입력받은 시간을 출력하는 멤버 함수를 작성하라.\\ | ||
+ | 시: -33 | ||
+ | 분: 77 | ||
+ | 15시 17분 | ||
+ | \\ | ||
+ | 답안 예시 | ||
+ | <sxh cpp> | ||
+ | #include < | ||
+ | using namespace std; | ||
+ | |||
+ | class Time { | ||
+ | private: | ||
+ | int hour, minute; | ||
+ | |||
+ | public: | ||
+ | Time(int h, int m) : hour(h), minute(m) { | ||
+ | while (hour < 0) hour += 24; | ||
+ | while (hour >= 24) hour -= 24; | ||
+ | while (minute < 0) minute += 60; | ||
+ | while (minute >= 60) minute -= 60; | ||
+ | } | ||
+ | |||
+ | void printTime() { | ||
+ | cout << hour << "시 " << minute << " | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | int main() { | ||
+ | int h, m; | ||
+ | |||
+ | cout << "시 : "; | ||
+ | cin >> h; | ||
+ | cout << "분 : "; | ||
+ | cin >> m; | ||
+ | |||
+ | Time t(h, m); | ||
+ | |||
+ | t.printTime(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | =====6. 접근 제어===== | ||
+ | ====6.1. 접근 지정자==== | ||
+ | 접근 제어란 외부에서 특정 멤버 변수나 함수에 접근하는 것을 제어하는 것이다.\\ | ||
+ | '' | ||
+ | '' | ||
+ | '' | ||
+ | 클래스의 모든 구성원은 기본적으로 private이므로 외부에서 직접 접근하기 위해서는 public 키워드를 사용해야 한다.\\ | ||
+ | |||
+ | ====6.2. 접근 제어의 필요성==== | ||
+ | 우리는 앞에서 Rectangle 클래스를 작성했다.\\ | ||
+ | 그런데 만약에 width와 height가 모두 public인데 실수로 이 값들을 0 이하로 변경했다면 어떨까? | ||
+ | 도형의 변 길이는 0 이하가 될 수 없으므로 이는 잘못된 값이 된다.\\ | ||
+ | 이러한 실수를 방지하기 위해 공개해도 되는 멤버와 공개해서는 안되는 멤버를 구분한다.\\ | ||
+ | |||
+ | ====6.3. 접근자와 설정자==== | ||
+ | Rectangle 클래스에서 width와 height 변수를 비공개로 설정했다면 객체의 멤버 변수 값을 직접 변경하거나 읽어올 수 없다.\\ | ||
+ | 따라서 우리는 private으로 선언된 멤버 변수를 외부로 전달하거나 외부에서 안전하게 멤버 변수의 값을 변경할 수 있는 함수를 만들어 사용한다.\\ | ||
+ | 이를 각각 접근자, 설정자라고 부른다. | ||
+ | |||
+ | <sxh cpp> | ||
+ | class Rectangle { | ||
+ | private: | ||
+ | int width = 1; | ||
+ | int height = 1; | ||
+ | public: | ||
+ | Rectangle(int w, int h) : width(w), height(h) {} | ||
+ | int getWidth() {return width} | ||
+ | int getHeight() {return height} | ||
+ | void setWidth(int w) : width(w) {} | ||
+ | void setHeight(int h) : height(h) {} // 설정자 | ||
+ | }; | ||
+ | |||
+ | int main() { | ||
+ | Rectangle r {2}; | ||
+ | r.setHeight(3); | ||
+ | cout << r.getWidth() << " " << r.getHeight(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ====예제==== | ||
+ | 다음 빈칸을 채워 자신의 학과, 학번, 이름이 출력되도록 만들어라. | ||
+ | <sxh cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | using namespace std; | ||
+ | |||
+ | class Student { | ||
+ | private: | ||
+ | ____________________ | ||
+ | ____________________ | ||
+ | ____________________ | ||
+ | public: | ||
+ | Student() : department(" | ||
+ | |||
+ | void setDepartment(__________) { | ||
+ | ____________________ | ||
+ | } | ||
+ | void setNum(__________) { | ||
+ | ____________________ | ||
+ | } | ||
+ | void setName(__________) { | ||
+ | ____________________ | ||
+ | } | ||
+ | string getDepartment() { | ||
+ | ____________________ | ||
+ | } | ||
+ | int getNum() { | ||
+ | ____________________ | ||
+ | } | ||
+ | string getName() { | ||
+ | ____________________ | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | int main() { | ||
+ | ____________________ | ||
+ | |||
+ | ____________________ | ||
+ | ____________________ | ||
+ | ____________________ | ||
+ | |||
+ | cout << " | ||
+ | cout << " | ||
+ | cout << " | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | 답안 예시 | ||
+ | <sxh cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | using namespace std; | ||
+ | |||
+ | class Student { | ||
+ | private: | ||
+ | string department; | ||
+ | int num; | ||
+ | string name; | ||
+ | public: | ||
+ | Student() : department(" | ||
+ | |||
+ | void setDepartment(string s) { | ||
+ | department = s; | ||
+ | } | ||
+ | void setNum(int n) { | ||
+ | num = n; | ||
+ | } | ||
+ | void setName(string s) { | ||
+ | name = s; | ||
+ | } | ||
+ | string getDepartment() { | ||
+ | return department; | ||
+ | } | ||
+ | int getNum() { | ||
+ | return num; | ||
+ | } | ||
+ | string getName() { | ||
+ | return name; | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | int main() { | ||
+ | Student s; | ||
+ | |||
+ | s.setDepartment(" | ||
+ | s.setNum(2020170716); | ||
+ | s.setName(" | ||
+ | |||
+ | cout << " | ||
+ | cout << " | ||
+ | cout << " | ||
+ | } | ||
+ | </ |