제 10장 C++ Hello!! C 언어 강성호 김학배 최우영
순서 제 10장 C++ 서론 C관점에서 개선된 C++ C++ 구축 C++ 클래스 객체 지향 프로그래밍 계승 다형성 기타 요약
서론 C++는 1980년 Bell 연구소에서 Bjarne Stroustrup에 의해서 개발 C++ 언어는 C에 여러 가지의 부가적인 기능을 더하였고 여기에다 객체의 개념을 도입 C++는 C와 같거나 객체 지향적인 스타일, 혹은 두 가지를 혼용한 스타일로 프로그램 하는 것이 가능 C++는 C 언어의 장점을 가지고 있으면서 기존의 C 구조를 개선하고 객체의 개념을 추가함으로써 강력한 기능을 제공
C관점에서 개선된 C++ 원형(prototype)화와 형 검사(type checking) 함수를 호출하는 경우 원형을 잘못 명시했을 경우는 컴파일 시 에러가 발생
C관점에서 개선된 C++ 원형(prototype)화와 형 검사(type checking) [예제 10-1] #include<stdio.h> extern type_c(); //C 언어형식으로 함수를 선언 extern type_num1(double x); //C++ 언어의 형식으로 함수를 선언 extern type_num2(const char*,int); int a,b; main(){ type_c(); //에러: 함수의 원형이 불분명 type_num1(a,b); //에러: 인자 수 불일치 type_num2(a,b); //에러: 첫 인자 형 불일치 }
C관점에서 개선된 C++ 엄격한 형검사 [예제 10-2] int max( int value1, int value2 ) return ((value1 > value2) ? value1 : value2); C++는 엄격하게 형을 따지는 언어이기 때문에 컴파일 시 모든 함수의 인자와 리턴형을 검사 함수의 원형은 컴파일러에게 컴파일 시에 형검사를 할 수 있도록 필요한 정보를 제공 컴파일러는 함수 원형과 호출시의 인자형이 서로 일치하지 않으면 자동 변환이 불가능한 경우에 컴파일 시 에러
C관점에서 개선된 C++ 엄격한 형검사 [예제 10-3] #include <math.h> extern double sin (double); int main(void){ double result; result = sin(60); //자동변환이 일어남 :result= sin(60.0) //c 컴파일러는 잘못된 코드 생성 return 0; }
C관점에서 개선된 C++ 엄격한 형검사 C++과 ANSI C와의 차이점 C++과 C는 함수 선언시에 비어있는 인자 리스트를 서로 다르게 해석하므로 C++에서는 인자 리스트가 비어있다면 그 함수가 인자를 가지지 않는다는 것을 표시하는 반면 ANSI C의 경우는 void로 인자를 가지지 않는다는 것을 표시
C관점에서 개선된 C++ 초기값(default) 매개변수 매개변수들은 초기값이 주어질 수 있음 만약에 함수의 매개변수들에 초기값 매개변수가 정의되어 있는 경우에 함수의 호출 시에 매개변수가 나타나지 않으면 함수의 원형에 있는 초기값이 매개변수에 전달된 것으로 간주
C관점에서 개선된 C++ 초기값(default) 매개변수 [예제 10-4] #include <iostream.h> int max(int value1, int value2 = 0) { // value2에 초기값으로 0을 지정 return ((value1 > value2) ? value1 : value2); } int main(void) { int x,y; x = max(4, 3); cout << x << ”\n”; y = max(-2); cout << y << ”\n"; return 0; [실행 결과] } 4
C관점에서 개선된 C++ 열거(enumeration) 데이터형의 확장 C++는 프로그램에서 심벌을 사용해서 상수(constant)를 표현하도록 하는 데이터형인 열거형을 제공 열거형의 각 원소들은 각 원소에 배정된 번지가 없다는 점에서 const로 선언된 데이터형과 차이 열거형을 사용하는 경우에 C와 C++는 약간의 차이 C의 경우에 열거형의 변수는 int형의 어떠한 값이 할당 C++에서는 열거형의 변수가 오직 열거자(enumerator)중의 하나의 형으로 할당
C관점에서 개선된 C++ (8) 선언확장 (declaration extension) 구조체나 열거형을 쓰는 경우에 구조체나 열거형의 이름 앞에 'struct'나 'enum'을 써 주지 않아도 됨
C++ 구축 주석문(comment) C++는 두 가지의 주석문을 붙이는 방법 C에서의 주석 쌍( /* */ )을 이용 주석 기호( // )를 이용 : 주석 기호의 다음 줄에서부터 줄 끝까지의 내용을 모두 주석으로 의미하는 기호 주석 쌍을 쓰는 경우는 설명해야할 내용이 많을 경우에 유리하고, 주석 기호를 이용하는 경우는 설명할 내용이 한 줄에 끝날 경우에 쓰는 것이 유리 [예제 10-5] int main(void){ ... y=3+x; /* C 형식 주석문 */ k=7+y; // C++ 형식 주석문 }
C++ 구축 상수형(constant type) 기호화된 상수는 상수 변수라고도 불림 C++에서는 'const'라는 키워드로 의해서 이름이 주어지게 되며 'const'라는 키워드가 맨 앞에 놓여져야 됨 기호화된 상수는 한번 값이 정의되면 그 값을 바꿀 수 없기 때문에 반드시 초기화가 필요 [예제 10-6] #include<iostream.h> const char a='A'; //상수 변수 a의 초기화 const int b; //에러: 상수 변수를 초기화시키지 않음 const double c=1.48; int main(void){ //A가 화면에 출력됨 cout<< a; c=2; //에러: 상수 변수는 값이 변화될 수 없음 return 0; }
C++ 구축 상수형(constant type) 상수 변수의 번지를 포인터에 대입하는 것도 에러 상수 변수의 번지를 포인터로 선언할 수 있음 상수 객체를 가리키는 상수 포인터도 정의 가능 [예제 10-7] const int a=0; int *p = &a; //에러: 상수 변수의 번지가 포인터에 대입됨 *p++; [예제 10-8] char *const str1 = "Hello"; // 상수 오브젝트를 가리키는 포인터 char const *str2 = "I am a boy"; // 상수 변수의 포인터
C++ 구축 참조형(reference type) C++에서는 '&'와 '*'의 두 연산자로 참조형을 정의 참조형은 변수에 대한 가명(alias)이라 불림 참조형, 즉 가명 앞에는 항상 '&'연산자가 위치해야 하고 어떠한 변수명을 가져야 함 [예제 10-9] int a,b; int &pa =a; double &c=b; //에러: 자신과 같은 형의 값으로만 초기화됨 int &d=18; //에러: 상수 참조가 아닌 경우 //는 자신과 같은 형의 변수 타입으로 //초기화되어야 함 const int &e= 24; //상수 오브젝트나 상수 포인터에 대한 참 //조는 data 값이나 자신과 같지 않은 변수 //타입으로 초기화 될 수 있다
C++ 구축 제 10장 C++ 참조에 의한 함수의 인자 전달 C++에서 함수의 인자 전달의 초기화 방식은 형식 인자들의 값호출을 사용 하에 인자를 함수에 전달하는 것으로 매개변수는 실제 인자 값의 복사값(copy) 값호출을 이용하게 되면 실제의 매개변수가 함수에 의해서 수정되는 것을 방지할 수 있음 C에서 인자로 사용된 변수의 값을 변경할 수 있는 경우는 매개변수는 포인터형으로 선언되어야 하고 함수는 '*' 연산자를 이용하여 변수를 조작할 수 있음 [예제 10-10] /* C에서의 참조 호출 방법: 포인터를 이용한 참조 호출 */ /* 두 값을 치환하는 함수 선언 */ void replace_c(int *a,int *b) { int temp; /* 임시저장소 선언 */ temp=*a; /* a값을 변수 temp에 저장*/ *a=*b; /* b값을 포인터변수 a에 저장 */ *b=temp; /* temp값을 b에저장 */ }
C++ 구축 제 10장 C++ 참조에 의한 함수의 인자 전달 C++에서는 C에서의 참조호출의 방법을 허용하면서도 매개변수를 함수에 패스하는 명료한 방식을 지원 C++에서는 함수의 선언문 안의 매개변수의 앞에 '&' 연산자를 위치함으로 참조호출을 이용 [예제 10-11] //C++만의 참조 호출 방법: 참조호출 void replace_c++(int &a,int &b){ //두 값을 치환하는 함수 선언 int temp; //임시저장소 선언 temp=a; //변수 a값을 변수 temp에 저장 a=b; //변수 b값을 변수 a에 저장 b=temp; //temp값을 변수 b에저장 }
C++ 구축 제 10장 C++ 참조에 의한 함수의 인자 전달 참조 매개변수를 사용하면 C의 예와 다르게 '&'와 '*'연산자를 사용할 필요가 없음 참조에 의한 매개변수의 전달은 효율적이지만 이 경우 매개변수의 값이 변하게 됨 만약 프로그래머가 참조로 매개변수를 전달하면서 실제의 값이 변하지 않게 하려면 상수 참조 매개변수를 쓰면 됨 [예제 10-12] struct my_age{ int age=9; }; //구조체 my_age의 상수 참조 매개변수 exp 선언 void R_my_age(const my_age& exp) { int x=exp.a; exp.a=0; //에러: 참조되는 상수 참조 } //매개변수는 변화 안됨
C++ 구축 new와 delete를 이용한 동적 메모리 할당 malloc를 사용하는 대신에 new연산자를 사용하면 여러 가지 장점을 얻을 수 있음 new는 할당되는 형의 크기를 자동으로 계산하기 때문에 sizeof 연산자가 필요가 없으며 할당되는 개체를 초기화 할 수 있음 [예제 10-13] p=new int[size]; //메모리관리자에게 size만큼의 기억장소를 //동적으로 할당하도록 함 delete p; //동적 메모리 할당 해제
C++ 구축 범위 연산자(scope operator) C와 C++의 경우에 함수 밖의 전역 변수와 동일한 이름의 변수를 함수 안에서 지역 변수로 정의해서 쓸 수 있음 C++에서는 지역 변수와 동일한 이름을 가지는 전역 변수를 범위 연산자 '::'를 사용해서 접근할 수 있음 [예제 10-14] #include<iostream.h> int a=10; //전역 변수 a의 초기화 int main(void){ int a=20; //지역 변수 a의 초기화 cout << "local variable a =" << a <<"\n"; //지역 변수 a값의 출력 cout <<"global variable a =" << :: a <<"\n"; //전역 변수 a의 출력 return 0; } [실행 결과] local variable a =20 global variable a =10
C++ 구축 오버로드 (overload) 함수 대부분의 C++의 연산자들은 단지 지정된 형태에서 정의 함수의 오버로드는 서로 다른 인자형에 대해서 같은 연산을 제공하는 같은 이름의 함수의 정의가 가능한 것을 의미 C++에서 둘 이상의 함수를 같은 이름으로 정의하는 경우에는 인자들의 개수나 인자의 형에 의해서 함수가 구별 [예제 10-15] #include<iostream.h> #define PI 3.141592654 double area(double r){ //원의 면적을 구하는 double형 함수선언 double area; area=PI*r*r; return(area); } 계속
C++ 구축 오버로드 (overload) 함수 [예제 10-15] (계속) float area(float r){ // 원의 면적을 구하는 float형 함수선언 float area; area=PI*r*r; return(area); } int main(void){ float a,b; double c,d; a=23.54; c=23.54; // 반지름의 초기화 b=area(a); //a를 넘겨주며 area를 호출 cout<< b <<"\n"; d=area(c); //a를 넘겨주며 area를 호출 cout<< d <<"\n"; return 0; } [실행 결과] 1740.86 1740.86
C++ 구축 오버로드 (overload) 연산자 C++는 대부분의 연산자들에게 중복을 허용 [예제 10-16] complex operator+(complex a,complex b) { return complex(a.real+b.real, a.imag+b.imag); }
C++ 구축 인라인(inline) 함수 인라인 함수는 함수에 있는 내용을 함수가 호출된 자리에 끼워 놓음으로써 속도를 증가시킴 인라인 함수는 대체로 크기가 작고 자주 호출되는 함수를 최적화하기 위한 수단
C++ 구축 [예제 10-17] #include<iostream.h> #include<stdio.h> #ifdef __cplusplus inline int max(int a, int b){ //함수 max()를 인라인 함수로 정의 return ((a > b) ? a : b); } #endif int main(void) { int x=5; int y=6; int z; z = max(x, y); // z=((x > y) ? x : y)로 컴파일시 확장 cout<<z; return 0; [실행 결과] 6
C++ 클래스 클래스의 정의 클래스는 여러 가지의 형을 가진 데이터 원소와 그 데이터를 다루기 위한 여러 연산의 집합체 'class'라는 키워드를 사용해 클래스를 정의 클래스는 데이터뿐만이 아니라 이러한 데이터를 조작하는 함수까지도 함께 가지고 있음 클래스는 클래스 머리와 클래스 몸체로 나뉨 클래스 머리는 'class'라는 키워드 다음에 클래스 이름을 씀 클래스 몸체는 괄호로 묶여진 일련의 내용들로 구조체와 마찬가지로 마지막에는 세미콜론이 항상 있거나 선언 리스트가 있어야 함 클래스 몸체에서는 데이터와 함께 데이터를 조작하는 함수가 함께 나타나게 되는데 클래스에 나타나는 데이터들을 클래스의 데이터 구성원(data member)라 하고 클래스에 나타나는 함수들을 클래스의 구성원 함수(member function)라고 함 데이터 구성원는 클래스를 데이터형으로 정의되는 변수의 기억장소 구조를 나타내게 되고 구성원 함수는 변수에 할당된 기억 장소를 조작하는 일을 하게 되며 데이터 구성원와 구성원 함수를 통칭하여 구성원라 함
C++ 클래스 클래스의 정의 [예제 10-18] class My_class{ private: //private 권한을 가지는 구성원의 영역 선언 static int my_private; //정적 데이터 구성원 protected: //protect 권한을 가지는 구성원의 영역 선언 int my_protected; //일반 protect 데이터 구성원 public: //public 권한을 가지는 구성원의 영역 선언 static void Openpub(); //정적 구성원 함수 My_class(); //객체 생성자 virtual ~My_class(); //객체 파괴자 virtual double My_const() const; //const 구성원 함수 virtual void My_virtual(); //가상 구성원 함수 }; //클래스 정의 끝
C++ 클래스 제 10장 C++ 클래스의 정의 클래스에 나타나는 구성원 중에서 'static'이라는 키워드가 사용되는 데이터 구성원와 구성원 함수가 정적 구성원 'const'라는 키워드와 함께 사용되는 구성원이 const 구성원 구성원 함수 중에서 'virtual'이라는 키워드가 함수 앞에서 사용되고 있는 구성원 함수는 가상 함수 'friend'라는 키워드가 함수 앞에 나타나는 구성원 함수는 친구 함수 함수의 이름이 클래스의 이름과 일치하는 경우에 이 함수는 객체 생성자라하며 클래스를 데이터형으로 사용하는 변수에 기억장소가 할당되는 경우에 자동으로 호출되어 할당된 기억장소를 초기화시키는 역할 클래스의 이름 앞에 '~'라는 문자가 사용되어 클래스와 같은 이름으로 사용되는 함수를 객체 파괴자라고 하는데 클래스를 데이터형으로 사용하는 변수의 기억 장소가 시스템에 반납되기 직전에 자동적으로 호출돼서 정의되어진 작업을 수행토록 함
C++ 클래스 클래스의 정의 데이터 구성원(data member) 데이터 구성원의 선언은 초기화 경우에 명시적으로 값을 할당하지 않다는 점을 제외하면 일반변수의 선언 방법과 같음 데이터형이 데이터 구성원를 선언하는데 이용되는 것과 마찬가지로 클래스도 데이터 구성원를 선언하는데 사용될 수 있음 만약 클래스에 대한 정의가 되지 않은 상태에 전방 선언을 하게되면 지금 선언중인 클래스에 대해서 참조형의 데이터 구성원 선언이 가능 구성원 함수(member function) 구성원 함수의 정의는 클래스 내부나 또는 외부에서 정의되어 질 수 있음 구성원 함수를 클래스 안에서 정의하는 경우에는 C와 동일한 방법으로 정의하며 이 경우의 구성원 함수는 인라인 함수의 특징을 가지므로 간단한 구조의 함수만이 표현되어 질 수 있음 복잡한 구조를 가진 함수들은 외부에서 정의되어야 하며 구성원 함수의 이름 앞에 항상 함수가 들어있는 클래스의 이름을 놓고 클래스와 함수의 이름을 '::' (범위 연산자)로 분리시켜야 함
C++ 클래스 제 10장 C++ 구성원의 접근 권한 'private', 'protected', 'public'의 세 키워드를 사용하여서 클래스 내부 구성원의 접근 권한을 부여 public 구성원들은 프로그램의 어느 곳에서나 직접 접근 가능 정보 은닉을 강화하는 클래스에서는 public 함수들은 그 클래스의 연산을 정의하는 구성원 함수들로 한정되어짐 정보의 보안을 위해서는 private나 protected 구성원를 쓰는 것이 바람직 private 구성원들은 구성원 함수들이나 클래스의 친구만이 접근 가능 정보의 보안을 강화하기 위해서는 모든 데이터를 private으로 선언해야 함 protected 구성원은 파생된 클래스에 대해서는 public인 것처럼 동작하지만 프로그램의 다른 부분에서는 private인 것처럼 동작
C++ 클래스 구성원 함수와 데이터 구성원의 접근 [예제 10-19] .... class My_class{....}; //My_class라는 클래스선언 My_class object_1; //My_class형의 객체 선언 object_1.My_virtual(); //object_1에 대해 구성원 함수 My_virtual호출 object_1.my_protected=1; //object_1의 데이터 구성원 my_protected에 1이라는 값을 저장 My_class *object_2 = &object_1; //데이터형의 포인터 변수 object_2를 정의 object_2 -> My_virtual(); // object_2의 구성원 함수 My_virtual() 호출 object_2 -> my_protected = 1; // object_2의 데이터 구성원 my_protected에 1이라는 값을 저장
C++ 클래스 구성원 함수와 데이터 구성원의 접근 클래스를 데이터형으로 사용하여 정의된 변수는 구조체와 마찬가지로 연산자 '.'을 사용하여서 데이터 구성원와 구성원 함수에 접근 가능 연산자 '.'를 이용하여 변수와 데이터 구성원를 연결하게 되면 변수에 할당되어 있는 기억장소 중에서 데이터 구성원에 해당되는 기억장소를 가리키게 됨 변수와 구성원 함수를 연결하면 변수에 할당되어 있는 기억장소를 이용하여서 구성원 함수를 실행시키라는 의미 변수에서 인스탄스의 포인터를 저장하는 경우는 '.' 대신에 '->' 연산자를 사용해서 변수를 데이터 구성원, 구성원 함수와 연결을 시킴 이 경우 클래스에 정의되어 있는 구성원의 접근 권한에 대해서 고려를 해야함
C++ 클래스 객체 생성자(constructor)와 객체 파괴자(destructor) 클래스에 정의되어 있는 구성원 함수 중에서 클래스의 이름이 구성원 함수의 이름과 일치하는 것을 객체 생성자라고 함 클래스의 이름과 같고 '~' 연산자가 함수의 이름 앞에 놓이는 경우에 이 함수를 객체 파괴자라고 함 대부분의 클래스는 1개 이상의 객체 생성자와 가상 함수로 정의되는 1개의 객체 파괴자를 정의 객체 생성자는 데이터형으로 클래스를 사용하여 변수를 정의하는 경우에 시스템에서 변수에 기억장소를 할당한 뒤에 자동으로 호출 클래스의 정의 시에는 변수에 할당된 기억장소를 초기화시키는 작업을 수행하는 명령어들로 객체 생성자를 정의해야 함 시스템은 데이터형으로 클래스를 사용하는 변수의 기억장소가 반납되기 전에 객체 파괴자를 호출하게 되므로 클래스를 정의하는 경우에는 변수의 기억장소가 반납되기 이전에 클래스에서 수행하는 작업들로 객체 파괴자를 정의해야 함
C++ 클래스 객체 생성자와 객체 파괴자 객체 생성자와 파괴자를 정의시 주의점 객체 생성자와 파괴자는 친구 함수나 정적 함수로 정의될 수 없음 객체 생성자와 파괴자는 리턴 값을 명시할 수 없고 리턴 되는 값의 데이터형을 지정할 수 없음 객체 생성자는 가상 함수로 정의되어 질 수 없지만 객체 파괴자는 가상 함수로 정의될 수 있음 클래스에서는 한 객체 생성자가 다른 객체 생성자와 매개변수의 수가 다르거나 형이 같지 않으면 2개 이상의 생성자가 존재할 수 있음 객체 생성자에는 매개변수가 존재할 수 있지만 객체 파괴자는 매개변수가 존재할 수 없음
C++ 클래스 클래스의 친구(friend) 비구성원 함수의 경우 이 함수를 친구라고 지정함으로써 마치 클래스에 정의되어 있는 구성원 함수와 같이 클래스에 정의되어 있는 모든 데이터 구성원와 구성원 함수를 자유롭게 이용할 수 있음 C++에서 친구 함수가 허용되는 이유는 두 개의 클래스가 동일한 함수를 공유해야 하는 상황에서 편의를 도모하기 위해
C++ 클래스 [예제 10-20] #include<iostream.h> class num2; //친구 함수에 num2라는 클래스를 알려주기 위함 class num1{ private: int number; public: friend int equal_or_not(num1 num1_ex, num2 num2_ex); void save_num(int a); }; class num2{ }; 계속
C++ 클래스 [예제 10-20] (계속) int equal_or_not(num1 num1_ex, num2 num2_ex){ if(num1_ex.number == num2_ex.number) return 1; else return 0; } //값을 number에 할당하기 위한 save_num의 정의 void num1::save_num(int a){ number=a; } void num2::save_num(int a){ 계속
C++ 클래스 [예제 10-20] (계속) int main(void){ num1 num1_ex; num2 num2_ex; num1_ex.save_num(5); num2_ex.save_num(5); //private구성원인 number에 각각 5라는 값을 할당 if(equal_or_not(num1_ex, num2_ex)==1) cout<< "equal\n"; else cout << "not equal"; return 0; } [실행 결과] equal
C++ 클래스 정적 클래스 구성원(member) 'static'이라는 키워드를 이용하여 정의하는 데이터 구성원와 구성원 함수를 정적 데이터 구성원와 정적 구성원 함수라 하고 이 두 가지를 통칭해서 정적 구성원라고 함 클래스의 구성원를 정적이라고 선언하는 경우에는 많은 클래스형의 변수가 선언된다 하더라도 오직 하나만의 정적 구성원만을 기억장소로 할당 클래스의 구성원를 정적 구성원로 선언하는 경우는 단 하나의 구성원 복사만이 허용이 되고 클래스의 모든 객체의 인스탄스가 그것을 공유하도록 하기 때문 정적 구성원 함수는 클래스에 선언된 모든 정적 데이터 구성원와 다른 정적 구성원 함수를 접근할 수 있음 정적 구성원 함수는 객체가 생성되기 전에 실행이 되기 때문에 구조체와 같이 연산자 '.' , 또는 '->' 등으로 호출되어질 수 없음 이 경우에는 정적 구성원 함수의 이름 앞에 '::' 연산자를 사용해서 클래스의 이름과 정적 구성원 함수를 분리함으로써 호출 가능 이 경우는 클래스형 객체의 인스탄스가 존재하지 않는 상황에서도 실행이 가능
C++ 클래스 const 객체와 const 구성원 함수 C++에서는 클래스를 내장된 int나 float와 같은 데이터형과 같이 취급하므로 'const'라는 키워드를 사용하여 객체를 정의 이러한 객체를 const 객체라고 하는데 이는 프로그램 중에 객체의 내용이 변할 수 없음을 의미 클래스형에서는 구성원 함수가 실행되면 객체의 내용이 바뀔 수 있기 때문에 이러한 문제를 해결하기 위해서 'const' 구성원 함수를 사용 const 구성원 함수는 함수가 실행되어도 객체의 내용을 변경시키지 않는 다는 것을 컴파일러에게 알려줌 const 객체의 내용은 const 구성원 함수 이외의 구성원 함수가 실행되는 경우에는 const 객체의 내용이 변경되어질 수 있기 때문에 const 객체는 const 구성원 함수만을 호출할 수 있도록 함
객체 지향 프로그래밍 객체 지향 프로그래밍 (object oriented programming) 객체 지향 프로그래밍에서 소프트웨어의 대응되는 변수나 함수들이 실제 세계에 있는 사실을 모델링 세상에 나와있는 모든 사물을 추상화 시켜서 같은 속성을 가지고 있는 객체들을 클래스로 나타내고 새롭게 만들어지는 클래스는 이미 존재하는 클래스의 성질을 계승받고 파생 특별한 성질을 가진 객체의 클래스는 이미 존재하는 클래스의 성질들을 상속받음으로써 파생되어 질 수 있음 객체 지향 프로그래밍은 사물의 속성과 행동을 나타내는 데이터와 함수에 정보를 캡슐화하고 객체에 대한 정보를 은닉함으로써 객체끼리의 접속을 통하여 정보를 주고받지만 다른 객체들이 어떻게 구현되어져 있는지에 대해서는 불허용 객체 지향 언어는 위에 나타난 객체, 클래스, 특성 계승 등의 개념을 사용하여 프로그램을 작성할 수 있는 프로그래밍의 언어
객체 지향 프로그래밍 제 10장 C++ 객체(object) 객체는 실제의 프로그램에서 데이터나 함수로 나타내어져서 사실이 논리적으로 대응되어지는 형태 객체 내에서는 어떤 코드나 데이터는 그 객체에 전용되어지고 그 객체 이외에는 다른 것에 의해서 접근되는 것을 방어해줌으로써 실수나 고의로 일어나는 사건을 방지 C++에서는 이러한 객체를 사용자 정의형 변수로 사용하기 때문에 프로그래머가 한 객체를 정의하게 되면 변수에 해당되는 데이터형과 함수를 만들게 됨
객체 지향 프로그래밍 다형성(polymorphism) 제 10장 C++ 다형성(polymorphism) 객체 위주 프로그래밍 언어에서는 하나의 이름이 관련은 있지만 다른 목적을 가질 경우에 사용되어 질 수 있도록 함 C++를 사용해서 작성된 프로그래밍에서는 하나의 프로그램 안에 동일한 이름을 가진 함수가 2개이상 존재할 수 있음 다형성이란 하나의 이름이 어떠한 행동을 가리키는 일반적인 사실을 나타내도록 하는 것
객체 지향 프로그래밍 계승(inheritance) 계승이란 한 객체가 다른 객체의 성질을 물려받는 것 계승의 예 한 학부를 계층적으로 분류 학교는 설립목적이나 크기로 종합대학과 전문대학으로 나뉠 수 있고 또 종합대학은 건물의 위치나 연구의 성격상 각 단과대학으로 나뉘어 지며 단과대학은 특정한 학부들로 분류 이러한 분류들은 어떠한 특징을 통해서 계층적으로 이루어짐 계층적 분류를 사용하여서 학부라는 부류에서 나타나는 특징만을 기술한다면 그 학부의 특징이 잘 드러날 수 있음 학부라는 객체는 단과대학이라는 객체의 특징을 모두 물려받게 되고 학교에서 학부까지는 계층 구조화 되어있기 때문에 종합대학이라는 객체의 특징도 물려받게 됨
계승 계승의 예 C++에서의 계승은 한 클래스를 다른 클래스의 선언문 안에 통합함으로써 실현됨 [예제 10-21] class college{ int college_prof; //단과대학의 교수 수 int location; //단과대학의 위치하는 방향 public: int get_college_prof(int a); //교수 수 저장 int get_location(int a); }; //단과대학의 위치저장 [예제 10-22] class department : public college{ //파생 클래스 정의 int student; //학부의 학생수 int opened_class; //학부의 개설된 과목수 int get_student(int a); //학부의 학생 수 저장 int get_opened_class(int a);}; //학부의 개설된 과목 수를 저장
계승 [예제 10-23] #include<iostream.h> class college{ int college_prof; //단과대학의 교수 수 int location; //단과대학의 위치 public: int get_college_prof(int a); //교수 수 저장 int get_location(int a); //단과대학 위치저장 }; class department : public college{ //파생 클래스 정의 int student; //학부의 학생수 int opened_class; //학부의 개설된 과목수 int get_student(int a); //학부의 학생수 저장 int get_opened_class(int a); //학부의 개설된 과목 수를 저장 }; 계속
계승 [예제 10-23] 계속 // 클래스에 나타난 함수의 정의 제 10장 C++ [예제 10-23] 계속 // 클래스에 나타난 함수의 정의 int college::get_college_prof(int a){ college_prof=a; return college_prof; } int college::get_location(int a){ location=a; return location; int department::get_student(int a){ student=a; return student; int department::get_opened_class(int a){ opened_class=a; return opened_class; } 계속
계승 [예제 10-23] 계속 int main(void){ department A; 제 10장 C++ [예제 10-23] 계속 int main(void){ department A; //department라는 형의 학부를 나타내는 변수 A변수 A가 가지는 값 int A_college_prof=10; int A_location=2; int A_student=200; int A_opened_class=15; //결과값을 출력 cout<<"professor="<<A.get_college_prof (A_college_prof)<<"\n"; cout<<"location="<<A.get_location (A_location) <<"\n"; cout<< "student=" <<A.get_student (A_student)<<"\n"; cout<< "Opened class="<<A.get_opened_class(A_opened_class); return 0; } [실행 결과] professor=10 location=2 student=200 opened class=15
클래스 기반(base) 클래스와 파생(derived) 클래스 파생 클래스의 객체 생성자와 파괴자 제 10장 C++ 기반(base) 클래스와 파생(derived) 클래스 파생 클래스의 객체 생성자와 파괴자 파생 클래스는 자신이 정의하고 있는 데이터 구성원 외에 기반 클래스로부터 계승받은 데이터 구성원의 기억장소도 가지고 있음 파생 클래스에서 객체 생성자를 정의하는 경우에는 객체 생성자와 함께 나타나는 기반 클래스의 객체 생성자가 실행이 된 후에 파생 클래스의 객체 생성자에 정의되어 있는 명령들이 실행이 됨 [예제 10-24] //객체 생성자 정의 형식 Child_My_class::Child_My_class():My_class (){ .… }; //객체 파괴자 정의 형식 Child_My_class::~Child_My_class(){
클래스 기반(base) 클래스와 파생(derived) 클래스 제 10장 C++ 기반(base) 클래스와 파생(derived) 클래스 만일 기반 클래스가 다른 기반 클래스를 가지고 있다면 먼저 객체 생성자에 나타나는 기반 클래스의 객체 생성자를 실행한 후에 파생 클래스의 객체 생성자를 실행하게 됨 파생 클래스에서 객체 생성자를 정의하는 경우는 클래스로부터 계승받은 기억장소의 초기화 작업을 파생 클래스에 정의되어 있는 기반 클래스의 객체 생성자에게 넘기고 파생 클래스에서 정의되어진 기억장소를 초기화시키는 작업만을 수행 객체 파괴자의 경우에는 파생 클래스의 객체 파괴자를 정의하는 경우에 기반 클래스의 객체 파괴자를 명시하지 않는데 이는 객체 파괴자의 순서가 정해져 있기 때문 객체 파괴자의 실행 순서는 객체 생성자가 실행되던 순서와 반대로 이루어짐
클래스 기반 클래스와 파생 클래스 파생 클래스를 정의할 때 유의점 제 10장 C++ 기반 클래스와 파생 클래스 파생 클래스를 정의할 때 유의점 기반 클래스에 정의되어 있는 구성원 중에서 protected와 public이라는 접근 권한을 가진 구성원는 파생 클래스에 계승이 되고 private라는 접근 권한을 가지고 있는 구성원는 파생 클래스에 계승되지 않음 기반 클래스의 접근 권한이 public으로 설정되어 있는 경우는 기반 클래스에서 정의되어진 접근 권한과 동일하게 파생클래스에서 나타나게 되고 기반 클래스의 접근 권한이 private로 설정되어 있는 경우에 기반 클래스에서 계승된 모든 구성원들은 파생 클래스에서 private 접근 권한을 가지게 됨 기반 클래스의 구성원 중에서 파생 클래스에서 동일한 이름을 가진 데이터 구성원와 구성원 함수가 정의되어 있다면 기반 클래스의 구성원는 계승되지 않음
클래스 다중 계승(multiple inheritance) 한 파생 클래스는 두 개 또는 그 이상의 클래스의 속성을 계승받을 수 있음 [예제 10-25] //A와 B라는 기반 클래스를 public 권한으로 //계승하는 Child_A_and_B class Child_A_and_B : public A, public B{ .... };
다형성 제 10장 C++ 초기 바인딩과 지연 바인딩 함수의 바인딩 : 프로그램에 함수 호출이 발생한 경우 실제로 실행되는 함수의 명령어들을 결정하는 과정 C++에서는 함수의 바인딩은 컴파일러에 의해서 수행되어 질 수도 있고 프로그램이 실행되는 경우에 수행될 수도 있음 초기 바인딩은 객체가 컴파일 시에 그의 함수 호출에 바인딩되는 것을 의미 C++는 가상 함수라는 예외를 제외하고는 초기 바인딩을 어떤 함수가 호출될 것인지를 결정하는데 필요한 모든 정보는 프로그램이 컴파일될 때 알려짐 이러한 예로는 일반 함수의 호출과 오버로드된 연산자와 함수의 호출이 대표적인 예이다. 후기 바인딩은 프로그램이 컴파일되어서 실행되어 질 때 함수의 바인딩이 이루어지는 것
다형성 가상 함수(virtual function) 가상 함수들은 프로그램이 컴파일되는 시에 바인딩이 이루어지는 것이 아니라 프로그램이 실행되는 경우에 구성원 함수가 실행되는 객체를 이용해서 바인딩이 이루어짐 이런 경우는 가상 함수는 프로그램이 실행될 때에, 함수를 실행시키는 객체가 소속되어 있는 클래스를 이용해서 함수 호출에 의해 이루어지는 함수의 명령어를 결정 일반적으로 클래스에서 다른 구성원 함수에 의해서 호출되어지는 구성원 함수들이 가상 함수로 정의 됨
기타 제 10장 C++ 데이터형 변환 C++에서는 클래스라는 사용자가 정의하는 데이터형을 사용하기 때문에 클래스와 클래스 사이에서의 데이터형을 변환할 수 있는 기능이 필요 C++자체에서 제공되어지는 데이터형의 변환은 C와 비슷하게 자동으로 변환이 되거나 아니면 캐스트 연산자에 의해서 변환이 됨 클래스를 사용하는 프로그램의 경우는 클래스와 클래스의 데이터형을 변화시키도록 객체 생성자와 변환 연산자를 이용 객체 생성자에서는 클래스의 인스탄스를 생성하는 일을 하기 때문에 프로그램에서 객체 생성자에 매개변수를 전달 가능 [예제 10-26] class Location{ //좌표에서 위치를 나타내는 클래스의 정의 int X,Y; //2차원 좌표의 변수 public: Location(); Location(int x); //1차원 좌표로 변환시키는 객체 생성자 };
기타 데이터형 변환 데이터형 변환자는 클래스형을 C++에서 제공되는 데이터형으로 변환 [예제 10-27] //좌표에서 위치를 나타내는 클래스의 정의 class Location{ int X,Y; //2차원 좌표의 변수 public: operator float_length() const; //Location을 float형태의 길이로 변환 }; Location::operator float_length() const{ return (float)(X*X+Y*Y); }
기타 제 10장 C++ this 키워드 구성원 함수는 호출되어지는 경우에 호출한 객체의 포인터로 자동으로 패스되는데 이 경우에 구성원 함수에서 사용되는 키워드 this는 객체의 포인터를 값으로 가지게 됨
기타 연산자의 친구 함수 연산자 함수는 클래스의 구성원가 아니라 친구로 되어 질 수 있음 제 10장 C++ 연산자의 친구 함수 연산자 함수는 클래스의 구성원가 아니라 친구로 되어 질 수 있음 친구 함수는 클래스의 구성원 함수는 아니지만 클래스에 정의되어 있는 데이터 구성원와 구성원 함수를 자유롭게 접근 가능 연산자 함수를 친구 함수로 쓰는 이유는 C++에서의 연산자 함수를 처리하는 방법의 문제 구성원 연산자 함수를 불러오는 경우에 객체에 대한 포인터는 this로 패스되어 짐 만약 이항 연산자의 경우는 왼쪽의 객체에 대해서 이항연산자를 호출하게 되는 것 양방향으로 실행되도록 하기 위해선 두 개의 함수를 사용하여서 두 개의 친구 함수를 사용하여서 오버로드를 시키면 됨
기타 연산자의 친구 함수 [예제 10-28] #include<iostream.h> class My_Plus{ public: int num; friend My_Plus operator+(My_Plus object,int a); friend My_Plus operator+(int a,My_Plus object); }; //객체 +정수의 연산자 함수 정의 My_Plus operator+(My_Plus object, int a){ My_Plus obj; obj.num = object.num + a; return obj; } 계속
기타 [예제 10-28] 계속 //정수 +객체의 연산자 함수 정의 제 10장 C++ [예제 10-28] 계속 //정수 +객체의 연산자 함수 정의 My_Plus operator+( int a, My_Plus object){ My_Plus obj; obj.num = object.num + a; return obj; } int main(void){ My_Plus Apple; Apple.num =3; Apple = 2 + Apple; Apple = Apple + 5; cout << Apple.num; return 0; [실행 결과] 10