본문 바로가기

프로그래밍 언어/열혈 C++

(14)
11-4 연산자 오버로딩2 스마트 포인터 스마트 포인터는 포인터처럼 동작하는 객체이다. class SmartPtr { private: Point * posptr; public: SmartPtr(Point * ptr) : posptr(ptr) { } Point& operator*() const { return *posptr; } Point* operator->() const { return posptr; } ~SmartPtr() { delete posptr; } }; 스마트 포인터는 전문 개발자들이 오랜 기간 걸쳐서 다듬어 가는 클래스이다. 그래서 개인적으로 스마트 포인터를 구현하는 경우는 드물고 라이브러리 속 스마트 포인터를 활용하는 경우가 대부분이다. 펑터 펑터는 함수처럼 사용하는 객체이다. 함수 호출에 인자 전달의 목적으로 사..
11-3 연산자 오버로딩2 new 연산자 오버로딩 new 연산자가 하는 일은 다음과 같다. 1. 메모리 공간의 할당 2. 생성자의 호출 3. 할당하고자 하는 자료형에 맞게 반환된 주소 값의 형 변환 세 가지 작업중 프로그래머가 오버로딩할 수 있는 것은 2번 생성자의 호출뿐이다. void * operator new(size_t size) { void * adr = new char[size]; // void * adr = malloc(size); return adr; } 컴파일러에 의해서 필요한 메모리 공간의 크기가 바이트 단위로 계산되어서 인자로 전달되기 때문에 크기가 1바이트인 char 단위로 메모리 공간을 할당해서 반환하였다. delete 연산자 오버로딩 void operator delete(void * adr) { delete..
11-2 연산자 오버로딩2 배열 클래스 C, C++의 기본 배열은 "경계검사를 하지않는다"라는 단점이 있다. arrObject[2]; arrObject를 객체로 보면 arrObject의 멤버함수 operator []를 매개변수 2를 전달하면서 호출하는 문장이다. int operator[] (int idx) { ... } arrObject.operator[] (2) 예시) 1차원 배열 #include #include using namespace std; class BoundCheckIntArray { private: int * arr; int arrlen; public: BoundCheckIntArray(int len) :arrlen(len) { arr=new int[len]; } int& operator[] (int idx) co..
11-1 연산자 오버로딩2 대입 연산자 디폴트 대입 연산자 복사 생성자뿐 아니라 대입 생성자도 정의하지 않으면 디폴트 대입 연산자가 생성된다. 디폴트 대입 연산자는 멤버대 멤버의 얕은 복사를 진행한다. 연산자 내에서 동적 할당을 한다면, 깊은 복사를 해야 한다면 직접 정의해야 한다. 복사 생성자 호출 예시) int main() { Point pos1(5, 7); Point pos2 = pos1; } 대입 생성자 호출 예시) int main() { Point pos1(5, 7); Point pos2; pos2 = pos1; } 복사 생성자와 유사한 만큼 유사한 문제점(똑같다)과 유사한 해결책을 가지고 있다. 바로 문자열을 멤버로 가지게 될 때 대입한 객체와 대입된 객체가 하나의 문자열을 참조하는 상황이 발생한다. 해결책은 1. 대입..
10-1. 연산자 오버로딩 1 자료형이 다른 대상으로 하는 연산 기본적으로 연산에 사용되는 두 피연산자의 자료형은 일치해야 한다. 하지만 연산자 오버 로딩을 통해서 예외를 둘 수 있다. Point operator*(int times) { Point pos(xpos*times, ypos*times); return pos; } 교환 법칙의 성립 위 예제로는 pos * 3은 실행이 되지만 3 * pos는 에러가 발생한다. (3.operator*(pos)가 될 수 없어서) 따라서 다음과 같은 정의도 필요하다. ( 전역함수를 기반으로 오버로딩을 해야한다,) class Point { ... friend Point operatr*(int times, Point &ref); }; Point operator*(int times, Point &ref)..
10. 연산자 오버로딩 1 연산자 오버로딩 함수를 오버로딩 하는 것 처럼 연산자도 오버로딩할 수 있다. 즉 연산자의 기본 기능 이외 다른 기능을 매개변수에 따라 추가할 수 있다. #include using namespace std; class Point { private: int xpos, ypos; public: Point(int x=0, int y=0) : xpos(x), ypos(y) { } void ShowPosition() const { cout
08 상속과 다형성 by 윤성우의 열혈 C++ 함수 오버라이딩 기초 클래스의 함수와 유도 클래스의 함수의 이름이 같고 매개변수의 자료형과 개수가 같을때 발생한다. 오버라이딩 된 기초 클래스의 함수는 유도 클래스의 함수에 가려진다. 오버라이딩 된 함수를 호출하고 싶다면 유도 클래스::함수 형태로 호출할 수 있다. 함수의 내부가 완전히 똑같아도 클래스내의 다른 멤버를 접근하기 위해 오버라이딩 하기도 한다. 객체 포인터 변수 객체 포인터는 객체 뿐만 아니라 객체를 상속하는 유도 클래스의 객체로도 초기화될 수 있다. (역은 안됨) 하지만 유도 클래스의 객체로 초기화해도 컴파일러는 포인터의 자료형으로 포인터 연산 가능성을 판단하기 때문에 유도 클래스의 멤버함수를 호출할 수 없다. 즉, C++ 컴파일러는 포인터를 이용한 연산의 가능성 여부를 판단할 때, 포인터..
07 상속의 이해 by 윤성우의 열혈 C++ 상속 A 클래스가 B클래스를 상속하게 되면 A클래스는 B클래스의 모든 멤버(변수, 함수)를 상속받는다. 이 때 A클래스를 유도 클래스, 자식 클래스 하위 클래스 등으로 부르고 B클래스를 기초 클래스, 부모 클래스, 상위 클래스등으로 부른다. (유도 클래스와 기초 클래스를 일반적으로 사용됨) 유도 클래스는 기초 클래스의 모든 멤버변수를 가져오기때문에 유도 클래스 생성자를 호출할때 기초 클래스의 모든 변수를 초기화해야한다. (기초 클래스를 초기화할때 기초 클래스의 생성자로 초기화하자) Student: public Person { private: int grade } Student(char *name, int age, int grade) :Person(name, age)// 기초 클래스의 생성자로 초기화 { ..