210 likes | 444 Views
처음으로 배우는 C 프로그래밍. 제 6 부 C++ 의 소개 제 14 장 추가적인 클래스 기능. 제 1 절 치환. 치환 (Assignment) 동일 클래스형의 객체간의 치환은 기본적으로 항상 가능하다 . 이때 치환은 내용의 비트별 (bitwise) 복사에 의해 수행된다 . Date a(4, 2, 99), b; b = a; // 비트별 복사에 의한 치환 치환 연산자 operator=( )
E N D
처음으로 배우는 C 프로그래밍 제6부 C++의 소개 제 14 장 추가적인 클래스 기능
제 1 절 치환 • 치환(Assignment) • 동일 클래스형의 객체간의 치환은 기본적으로 항상 가능하다. • 이때 치환은 내용의 비트별(bitwise) 복사에 의해 수행된다. Date a(4, 2, 99), b; b = a; // 비트별 복사에 의한 치환 • 치환 연산자 operator=( ) • 언어에서 기본적으로 제공하는 디폴트(default) 치환 연산 대신 다른 형태의 치환 연산을 하고자 할때는 치환 연산자를 재정의할 수 있다. • 치환 연산자의 형태 void operator=(class-name &); void Date::operator=(Date &newdate) { day = newdate.day; month = newdate.month; year = newdate.year; }
제 1 절 치환 • 복사 생성자 (copy constructor) • 생성되는 객체를 기존의 객체로 초기화할 때 사용되는 생성자 • 복사 생성자의 선언 형태 class-name(class-name &); Date(Date &) • 복사 생성자의 사용예 Date a = b;또는 Date a(b); • 복사 생성자는 객체 선언에서 초기화할 때 이외에, 함수 인자에 객체를 전달할 때와, 객체를 함수에서 반환할 때 사용된다. • 치환(assignment)는 이미 존재하는 객체에 대해서 값을 설정하는 것은 초기화(initialization)와는 다르다.
제 1 절 치환 • 베이스/멤버 초기화 • 생성자의 베이스/멤버 초기화 리스트를 사용하여 데이터 멤버를 초기화시킬 수 있다. Class Date { int month, day, year; public: Date(int mo = 4, int da = 1, int yr = 96) : month(mo), day(da), year(yr) { } };
제 2절 추가적인 클래스 특징 • 클래스 유효 범위(scope) • 데이터 멤버와 멤버 함수 이름은 클래스 유효범위내에 지역적이다. • 전연 변수 이름이 클래스 내에서 재사용되면 전역 변수는 클래스 데이터 멤버에 의해 은닉된다. • 멤버 함수는 선언된 클래스에 지역적이고, 그 클래스로 선언된 객체에 의해서만 사용될 수 있다. • 멤버 함수의 지역변수는 동일한 이름을 갖는 클래스의 데이터 멤버를 은닉한다.
제 2절 추가적인 클래스 특징 • 정적(static) 클래스 멤버 • 클래스의 모든 객체들이 공유하는 (동일한 저장공간을 갖는) 데이터 멤버 • 정적 클래스 멤버는 클래스 선언부에서 static 이란 키워드 부가하여 선언하고, 실제 기억공간을 할당하는 정의는 클래스 밖에 해야 한다. Class Employee { private: static float tax_rate; // 정적 클래스 멤버 선언 int id_num; public: Employee (int); void display( ); }; float Employee::tax_rate = 0.005; // 정적 클래스 멤버 정의
제 2절 추가적인 클래스 특징 • 정적(static) 멤버 함수 • 정적 멤버 만을 접근하는 멤버 함수 • 함수 선언시에 static이란 키워드만 붙이면 정적함수가 된다. • 객체가 만들어지기 전에 호출 가능하다. Class Employee { static float tax_rate; // 정적 멤버 public: Employee(int); static void disp( ); // 정적 멤버 함수 }; void main(void) { Employee::disp( ); // 정적 함수 호출 // ... }
제 2절 추가적인 클래스 특징 • this포인터 • 멤버 함수를 호출한 객체를 가리키는 포인터 • 멤버 함수가 호출될때 자동으로 해당 멤버 함수에 숨겨진 인자로 전달됨 Date::Date(int mm = 7, int dd = 4, int yy = 94) { month = mm; day = dd; year = yy; } this 포인터를 명시적으로 사용한 멤버함수 Date::Date(int mm = 7, int dd = 4, int yy = 94) { this->month = mm; this-> day = dd; this-> year = yy; }
제 2절 추가적인 클래스 특징 • 프렌드(friend) 함수 • 클래스의 멤버 함수가 아닌 것 중에서 멤버 함수와 동일한 데이터 멤버 및 멤버 함수에 대한 사용(접근) 권한을 갖는 함수 • 프렌드 함수의 정의 class Date { int month, day, year; public: Data(int, int, int); void showdate( ); friend int get_month(Data a); // 프렌드 함수 선언 }; int get_month(Data a) // 프렌드 함수로 사용되는 일반 함수 { return a.month; }
제 3 절 연산자 함수 • 연산자(operator) 함수 • 치환 연산자를 재정의한 것 처럼 C++에서는 기존의 연산자를 재정의할 수 있다. • 재정의 될 수 있는 연산자 • ( ) (함수호출), [ ] (배열의 원소), -> (포인터), new, delete • ++, --, - (단항 음수 부호), !(논리 부정), ~(비트별 보수), * (역참조) • *, /, %, +, - (산술 연산) • <<, >> (이동(shift) 연산) • <, <=, >, >=, ==, !=, &&, || (논리 연산) • &, ^, | (비트별 연산) • =, +=, -=, *=, /=, %=, &=, ^=, |=, <<=, >>= • , (쉼표) • 위에 없는 기호에 대해서는 연산자가 재정의 될 수 없다. • 새로운 연산자 기호는 생성될 수 없다. • C++ 연산자의 우선순위와 결합법칙은 바뀔 수 없다.
제 3 절 연산자 함수 • 연산자 함수 - 계속 • C++의 내장 데이터형에 대해서는 연산자가 재정의될 수 없다. • 단항 연산자가 이항 연산자로 재정의될 수도 없고, 이항 연산자가 단항 연산자로 재정의될 수 없다. • 연산자 함수는 클래스의 멤버이거나, 적어도 하나 이상의 클래스를 가져야 한다. • 연산자 함수는 멤버 함수나 프렌드 함수로 정의된다. Class Date { int month, day, year; public: Date(int, int, int); Date operator+(int); // + 연산자 중복 void showdate(void); }; Date::Date(int mm = 0, int dd = 0; int yy = 0) { month = mm; day = dd; yy = year; } Date Date::operator+(int days) { Date temp; temp.day = day+days; temp.year = year; temp.month = month; while (temp.day > 30) { temp.month++; temp.day-= 30; } while (temp.month > 12) { temp.year ++; temp.month -= 12; } return temp; }
제 3 절 연산자 함수 • 연산자 함수 - 계속 void Date::showdata(void) { cout << month << “/” << day << “/” << year; } void main(void) { Date a(4,1, 99), b; cout << “The initial data is “; a.showdate( ); b = a + 284; // b = a.operator+(284); 연산자 함수 호출 cout << “\nnew data is “; b.showdate; }
제 3 절 연산자 함수 • 치환 연산자 • 다중 치환을 위한 치환 연산자 중복 • a = b = c; 는 a = (b = c);와 같이 오른쪽 부터 처리된다. • 이때 (b = c;) 처리 결과가 a 에 치환되기 때문에, 치환 연산자 함수의 반환값이 b에 치환되는 값을 갖는 객체이어야 한다. Date operator=(Date &newdate) { day = newdate.day; month = newdate.month; year = newdate.year; return *this; // 치환 연산자 함수를 호출하는 객체 자체를 반환 } Date a(4, 1, 99), b, c; c = b = a; c.operator=(b.operator=(a));
제 4 절 데이터형 변환 • 내장형에서 내장형으로 변환 • 예) int val = (int) 14.3; float val2 = float(143); • 내장형에서 사용자 정의 데이터형 (클래스)로의 변환 • 형변환(type conversion) 생성자 사용 Date::Date(long findate) // long형을 Date형으로 변환하는 생성자 { year = int (findate/10000.0); month = int ((findate - year*10000.0)/100.0); } Date a; a = Date(991225); // long형 값을 Date형으로 변환하는 문장
제 4 절 데이터형 변환 • 사용자 정의형(클래스)에서 사용자 정의형으로의 변환 • 형변환 연산자 사용 • 형변환 연산자에서 연산자 이름은 변환될 클래스 이름이 된다. • 예를 들어, Date 클래스형 객체를 IntDate 클래스형 객체로 변환하고자 하는 경우, Date 클래스 내에 IntDate형으로의 형변환 연산자를 선언한다. Date::operatorIntDate( ) { // } • 사용자 정의형에서 내장형으로의 변환 • 형변환 연산자 사용 • 형변환 연산자에서 연산자 이름은 변환될 내장형 이름이 된다 Date::operatorlong( ) { // }
제 5 절 클래스 상속 • 상속(inheritance) • 어떤 기존 클래스로 부터 새로운 클래스를 파생시키는 것 • 기존 클래스 : 베이스(base) 클래스/ 부모(parent) 클래스/상위(super) 클래스 • 파생된 클래스 : 파생(derived) 클래스/자식(child) 클래스/하위(sub) 클래스 • 파생 클래스는 베이스 클래스의 모든 데이터 멤버와 멤버 함수를 포함하는 완전히 새로운 클래스이다. • 파생 클래스에는 그 클래스만의 새로운 데이터 멤버와 멤버 함수를 추가할 수 있으며, 베이스 클래스의 함수를 재정의할 수도 있다. • 두 개 이상의 베이스 클래스를 갖는, 즉 다중상속하는 파생 클래스도 정의할 수 있다. • 파생 클래스 정의 class 파생-클래스-이름: 접근명세 베이스-클래스-이름
제 5 절 클래스 상속 • 클래스 내에서의 접근명세(Access specification) • private(전용), public(공용), protected(보호) • private 영역내의 멤버 • 클래스 멤버 함수나 프렌드 함수에 의해서만 접근(사용) 가능 • 파생 클래스에서는 베이스 클래스의 private 영역 멤버 사용 불가 • public 영역 내의 멤버 • 클래스 멤버든 비멤버든 사용 가능 • 파생 클래스에서도 베이스 클래스의 public 영역 멤버 사용 가능 • protected 영역 내의 멤버 • 클래스 멤버 함수나 프렌드 함수에 의해서만 접근(사용) 가능 • 파생 클래스에서는 베이스 클래스의 protected 영역 멤버 사용 가능
제 5 절 클래스 상속 • 클래스 상속시의 접근 명세 • private • 베이스 클래스의 모든 멤버를 private 영역의 멤버로 간주 • 파생 클래스를 통해서 베이스 클래스의 public 영역 멤버의 사용도 불가 • 베이스의 private, public, protected 멤버 파생 클래스의 private 멤버 • public • 베이스 클래스의 멤버를 베이스 클래스에서의 접근명세대로 파생 클래스에 상속 • 베이스의 private 멤버 파생 클래스의 private 멤버 • 베이스의 public 멤버 파생 클래스의 public 멤버 • 베이스의 protected 멤버 파생 클래스의 protected 멤버 • protected • 베이스의 private 멤버 파생 클래스의 private 멤버 • 베이스의 public, protected 멤버 파생 클래스의 protected 멤버
제 5 절 클래스 상속 • 파생 클래스의 예 Class Circle // 베이스 클래스 { protected: double radius; public: Circle (double r = 1.0) { radius = r; } double calval(void) { return (pi*radius*radius); } }; Class Cylinder : public Circle // 파생 클래스 { protected: double length; public: Cylinder(double r = 1.0, double l = 1.0): Circle(r), length(1) { } double calval (void) ; // 함수 재정의 }; double Cylinder::calval(void) { return (length*Circle::calval( )); }
다형성(polymorphism) 베이스 클래스와 파생 클래스가 같은 이름의 함수를 가지고 있을 때, 포인터가 베이스 클래스 객체가 가리킬 때 포인터를 통해 해당 함수를 호출하면 베이스 클래스의 함수가 수행되고, 포인터가 파생 클래스 객체를 가리킬 때는 파생 클래스의 함수가 수행되도록 하는 것 포인터를 통한 동적 바인딩을 위해 이와 같이 다형성을 제공할 함수들은 가상 함수(virtual function)로 정의한다. 가상 함수는 멤버 함수 앞에 virtual 이란 키워드만 부여함으로써 가상 함수가 된다. 제 5 절 클래스 상속
제 5 절 클래스 상속 • 다형성 지원을 위한 가상 함수 사용예 class Two: public One { public : virtual float f1(float); }; float Two::f1(float num) { return (num/3); } void main(void) { One object_1; Two object_2; One *ptr; ptr = &object_1; cout << “object_1” << ptr->f1(12) << endl; ptr = &object_2; cout << “object_2” << ptr->f1(12 ) << endl; } class One { protected: float a; public : One(float); virtual float f1(float); float f2(float); }; One::One(float val = 2) { a = val; } float One::f1(float num) { return (num/2); } float One::f2(float num) { return (pow(f1(num),2)); }