멤버함수 중첩( 복사 생성자 ) - 연사자 중첩 - 동적 메모리를 가지는 클래스를 지원 하도록 멤버 함수 작성

Slides:



Advertisements
Similar presentations
7 장 프렌드와 연산자 중복 1 명품 C++. 친구란 ? 2 우리 집 냉장고 내 침대 우리 집 TV 우리 집 식탁 친구 친구 ? 내 가족의 일원은 아니지만 내 가족과 동일한 권한을 가진 일원으로 인정받은 사람.
Advertisements

01_ 가상 함수를 사용한 다형성의 구현 02_ 오버라이딩
명품 C++ 프로그래밍 3장. 클래스와 객체.
ㅎㅎ 구조체 구조체 사용하기 함수 매개변수로서의 구조체 구조체 포인터와 레퍼런스 구조체 배열.
ㅎㅎ 구조체 C++ 프로그래밍 기초 : 객체지향의 시작 구조체 사용하기 함수 매개변수로서의 구조체 구조체 포인터와 레퍼런스
쉽게 풀어쓴 C언어 Express 제11장 포인터 C Express Slide 1 (of 27)
ㅎㅎ C++ 프로그래밍의 첫 걸음 C++로 프로그래밍한다는 것의 의미 세상에서 가장 간단한 C++ 프로그램
C++ Espresso 제1장 기초 사항.
클래스 class, 객체 object 생성자 constructor 접근 access 제어 이벤트 event 처리.
9장. C 언어의 핵심! 함수. 9장. C 언어의 핵심! 함수 9-1 함수의 정의와 선언 main 함수 다시 보기 : 함수의 기본 형태 { } 그림 9-1.
제 9 장 구조체와 공용체.
컴퓨터 프로그래밍 기초 [Final] 기말고사
8. 객체와 클래스 (기본).
제12장 다형성과 가상함수 다형성의 개념을 이해한다. 상향 형변환의 개념을 이해한다. 가상 함수의 개념을 이해한다.
자료 구조: Chapter 3 (2)구조체, 포인터
3장. 변수와 연산자. 3장. 변수와 연산자 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, / 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, /
윤성우의 열혈 C 프로그래밍 윤성우 저 열혈강의 C 프로그래밍 개정판 Chapter 12. 포인터의 이해.
제 6장. 생성자와 소멸자 학기 프로그래밍언어및실습 (C++).
6. 기본 클래스 프로그래밍 6 컴퓨터공학과 신동일.
상속이란? - 기반클래스로부터 다른 클래스를 파생하는 법 protected란? 가상함수 (virtual function)
5장. 참조 타입.
제 3장. C보다 나은 C++ II.
다중 상속 - 가상 상속 추상 자료형 순수 가상함수
명품 C++ 7장 프렌드와 연산자 중복.
11장. 포인터 01_ 포인터의 기본 02_ 포인터와 Const.
C ++ 프로그래밍 시작.
정적 멤버 변수/정적 멤버 함수 - friend 함수/클래스 template
C++ Espresso 제12장 템플릿.
명품 C++ 4장. 객체 포인터와 객체 배열, 객체의 동적 생성.
23장. 구조체와 사용자 정의 자료형 2.
배열이란? 배열의 선언? - 배열과 포인터의 관계? 문자열이란? 문자배열 연결 리스트
스택(Stack) 김진수
14장. 포인터와 함수에 대한 이해.
14. 예외처리.
C++ 프로그래밍 년 2학기 전자정보공학대학 컴퓨터공학부.
C++ 프로그래밍 년 2학기 전자정보공학대학 컴퓨터공학부.
C#.
13. 연산자 오버로딩.
제14장 예외처리와 템플릿 예외 처리의 개요를 학습한다. 예외 처리를 적용할 수 있다. 템플릿의 개념을 이해한다.
사용자 함수 사용하기 함수 함수 정의 프로그램에서 특정한 기능을 수행하도록 만든 하나의 단위 작업
제5장 생성자와 접근제어 객체 지향 기법을 이해한다. 클래스를 작성할 수 있다. 클래스에서 객체를 생성할 수 있다.
3장 상수 변수 기본 자료형 키워드와 식별자 상수와 변수 기본 자료형 형변환 자료형의 재정의.
명품 C++ 9장 가상 함수와 추상 클래스.
제2장 제어구조와 배열 if-else 문에 대하여 학습한다. 중첩 if-else 문에 대하여 학습한다.
3장. 변수와 연산자 교안 : 전자정보통신 홈페이지 / 커뮤니티/ 학술세미나
Lesson 2. 기본 데이터형.
Chapter6 : JVM과 메모리 6.1 JVM의 구조와 메모리 모델 6.2 프로그램 실행과 메모리 6.3 객체생성과 메모리
제 12장. 사용자 정의형으로서의 클래스 학기 프로그래밍언어및실습 (C++).
컴퓨터 프로그래밍 기초 - 10th : 포인터 및 구조체 -
컴퓨터 프로그래밍 기초 - 8th : 함수와 변수 / 배열 -
루프와 카운트 Looping and counting
멤버 함수인 operator+()가 실행, 또는 전역 함수인 operator+()가 실행 Point p3 = p1+p2; 에서
C++ Espresso 제11장 예외 처리와 형변환.
제8장 포인터와 동적객체 생성 포인터의 개념을 이해한다. 포인터와 관련된 연산을 이해한다.
A Basic of C++.
12. 상속 : 고급.
객체기반 SW설계 팀활동지 4.
제 6 장 함수(functions).
Chapter 13. 템플릿(Template) 1
처음으로 배우는 C 프로그래밍 제6부 C++의 소개 제 14 장 추가적인 클래스 기능.
Chapter 2 C++ 함수와 네임스페이스. 최호성.
클래스 : 기능 CHAPTER 7 Section 1 생성자(Constructor)
중복 멤버의 처리 조 병 규 한 국 교 통 대 학 교 SQ Lab..
제 8장. 클래스의 활용 학기 프로그래밍언어및실습 (C++).
3. 모듈 (5장. 모듈).
Static과 const 선언 조 병 규 한 국 교 통 대 학 교 SQ Lab..
윤성우의 열혈 C++ 프로그래밍 윤성우 저 열혈강의 C++ 프로그래밍 개정판 Chapter 05. 복사 생성자.
1. 지역변수와 전역변수 2. auto, register 3. static,extern 4. 도움말 사용법
29장. 템플릿과 STL 01_ 템플릿 02_ STL.
상속 (Inheritance) private 전용부분 전용부분 공용부분 공용부분 public 기본 클래스
Presentation transcript:

멤버함수 중첩( 복사 생성자 ) - 연사자 중첩 - 동적 메모리를 가지는 클래스를 지원 하도록 멤버 함수 작성 고급 함수들 멤버함수 중첩( 복사 생성자 ) - 연사자 중첩 - 동적 메모리를 가지는 클래스를 지원 하도록 멤버 함수 작성

중첩된(Overload) 멤버 함수 멤버 함수 중첩 (Overloading) 매개 변수의 수나 종류가 다른 같은 이름을 가진 멤버 함수 <Tip> 중첩 시 같은 코드를 중복 시키지 않도록 하는 것이 프로그램 수정 시 오류를 방지 할 수 있음

#include <iostream> class Rectangle { public: Rectangle(int width, int height); ~Rectangle(){} // overloading void DrawShape() const; void DrawShape(int aWidth, int aHeight) const; private: int itsWidth; int itsHeight; }; Rectangle::Rectangle(int width, int height) itsWidth = width; itsHeight = height; } list 10.1

void Rectangle::DrawShape() const { DrawShape( itsWidth, itsHeight); } void Rectangle::DrawShape(int width, int height) const for (int i = 0; i<height; i++) for (int j = 0; j< width; j++) std::cout << "*"; std::cout << "\n"; int main() Rectangle theRect(30,5); std::cout << "DrawShape(): \n"; theRect.DrawShape(); std::cout << "\nDrawShape(40,2): \n"; theRect.DrawShape(40,2); return 0;

기본값(Default value) 사용 클래스 멤버 함수도 기본값 사용 가능 기본값 사용 멤버 함수 vs. 중첩된 멤버 함수 합당한 기본값이 없을 때 전혀 다른 알고리즘을 사용할 때 매개변수 목록에서 다른 형을 사용하길 원할 때

#include <iostream> using namespace std; class Rectangle { public: // constructors Rectangle(int width, int height); ~Rectangle(){} void DrawShape(int aWidth, int aHeight, bool UseCurrentVals = false) const; private: int itsWidth; int itsHeight; }; Rectangle::Rectangle(int width, int height) itsWidth = width; itsHeight = height; } list 10.2

void Rectangle::DrawShape( int width, int height, bool UseCurrentValue) const { int printWidth; int printHeight; if (UseCurrentValue == true) printWidth = itsWidth; printHeight = itsHeight; } else printWidth = width; printHeight = height; for (int i = 0; i<printHeight; i++) for (int j = 0; j< printWidth; j++) cout << "*"; cout << "\n";

int main() { // initialize a rectangle to 30,5 Rectangle theRect(30,5); cout << "DrawShape(0,0,true)...\n"; theRect.DrawShape(0,0,true); cout <<"DrawShape(40,2)...\n"; theRect.DrawShape(40,2); return 0; }

기본 생성자(default constructor) 매개 변수가 없는 생성자 생성자가 없을 시 컴파일러가 자동 생성 하나의 사용자 생성자가 있다면 컴파일러는 자동 생성 하지 않음 프로그래머가 멤버 변수를 초기화 하기 위해 매개변수가 없는 기본 생성자를 만들 수 있음 생성자 중첩 생성자도 다른 멤버함수처럼 중첩 가능

#include <iostream> using namespace std; class Rectangle { public: Rectangle(); Rectangle(int width, int length); ~Rectangle() {} int GetWidth() const { return itsWidth; } int GetLength() const { return itsLength; } private: int itsWidth; int itsLength; }; Rectangle::Rectangle() itsWidth = 5; itsLength = 10; } Rectangle::Rectangle (int width, int length) itsWidth = width; itsLength = length; list 10.3

int main() { Rectangle Rect1; cout << "Rect1 width: " << Rect1.GetWidth() << endl; cout << "Rect1 length: " << Rect1.GetLength() << endl; int aWidth, aLength; cout << "Enter a width: "; cin >> aWidth; cout << "\nEnter a length: "; cin >> aLength; Rectangle Rect2(aWidth, aLength); cout << "\nRect2 width: " << Rect2.GetWidth() << endl; cout << "Rect2 length: " << Rect2.GetLength() << endl; return 0; }

객체 초기화 예) Rectangle::Rectangle(): itsWidth(5), itsLength(10) { } 초기화 단계에서 멤버변수를 초기화 할 수 있음 : 멤버변수(초기값), … , 멤버변수(초기값) 예) Rectangle::Rectangle(): itsWidth(5), itsLength(10) { } Rectangle::Rectangle (int width, int length): itsWidth(width), itsLength(length)

복사 생성자(Copy Constructor) 동일 클래스 형에 대한 참조자를 하나의 매개변수로 가지는 생성자 이를 const화 하는 것이 좋음 복사 생성자의 호출 객체 생성 시 자신의 클래스 형으로 된 객체를 인수로 전달하는 경우 CAT Tom(Frisky); CAT Tom = Frisky; 객체를 call by value로 전달 시 함수에 의해 객체 반환 시 기본 복사 생성자 컴파일러가 기본적으로 제공 각 멤버변수들을 새로운 객체의 멤버변수에 복사 CAT (const CAT & theCat) ; 얕은 복사 (shallow copy) 자유 기억 장소를 가리키는 포인터가 멤버변수로 있을 경우 문제 발생

얕은 복사 Cat newCat(oldCat) ; 둘 중 하나만 소멸 시 해결책 : 깊은 복사 (deep copy) oldCat 소멸자에 의해 자유기억공간 반환 존재하는 객체의 포인터는 실종된 포인터 해결책 : 깊은 복사 (deep copy) 복사 생성자를 통한 별도의 메모리 할당 oldCat newCat 자유공간에 대한포인터 oldCat newCat

#include <iostream> using namespace std; class CAT { public: CAT(); //default constructor CAT (const CAT &); // copy constructor ~CAT(); // destructor int GetAge() const { return *itsAge; } int GetWeight() const { return *itsWeight; } void SetAge(int age) { *itsAge = age; } private: int *itsAge; int *itsWeight; }; list 10.5

CAT::CAT() { itsAge = new int; itsWeight = new int; *itsAge = 5; *itsWeight = 9; } CAT::CAT(const CAT & rhs) *itsAge = rhs.GetAge(); *itsWeight = *(rhs.itsWeight); CAT::~CAT() delete itsAge; itsAge = 0; delete itsWeight; itsWeight = 0;

int main() { CAT frisky; cout << "frisky's age: " << frisky.GetAge() << endl; cout << "Setting frisky to 6...\n"; frisky.SetAge(6); cout << "Creating boots from frisky\n"; CAT boots(frisky); cout << "boots' age: " << boots.GetAge() << endl; cout << "setting frisky to 7...\n"; frisky.SetAge(7); cout << "boot's age: " << boots.GetAge() << endl; return 0; }

연산자 중첩 내장형(정수형, 실수형, 문자형) C++ class : 사용자 정의형 class에 대한 특정 기능의 구현 내장 연산자(+, -, *, /)를 가지고 있음 C++ class : 사용자 정의형 사용자 연산자 지원 가능 class에 대한 특정 기능의 구현 멤버함수를 이용하는 방법 연산자 중첩 내장형에 대한 중첩은 불가능 상식밖에 있는 연산자 중첩 금지

#include <iostream> using namespace std; class Counter { public: int GetItsVal()const { return itsVal; } void SetItsVal(int x) {itsVal = x; } private: int itsVal; }; Counter::Counter(): itsVal(0) {} int main() Counter i; cout << "The value of i is " << i.GetItsVal() << endl; return 0; } list 10.6

#include <iostream> using namespace std; class Counter { public: int GetItsVal()const { return itsVal; } void SetItsVal(int x) {itsVal = x; } void Increment() { ++itsVal; } void operator++ () { ++itsVal; } private: int itsVal; }; Counter::Counter(): itsVal(0) {} int main() Counter i; cout << "The value of i is " << i.GetItsVal() << endl; i.Increment(); ++i; return 0; } list 10.8

중첩 연산자 함수에서의 반환값 형 list 10.8의 문제점 Counter a = ++ i; 중첩 연산자 함수에서의 반환 연산자함수의 반환 형 없음 중첩 연산자 함수에서의 반환 임시 객체를 만든 뒤 이를 반환 (리스트 10.9) 이름 없는(nameless) 임시 객체 반환 (리스트 10.10) 값을 가지는 생성자를 가지는 경우 반환값으로 생성자의 결과를 반환 임시 객체를 만드는 비용 감소 this 포인터 사용 (리스트 10.11) Counter a = ++ i;

#include <iostream> using namespace std; class Counter { public: int GetItsVal()const { return itsVal; } void SetItsVal(int x) {itsVal = x; } void Increment() { ++itsVal; } Counter operator++ (); private: int itsVal; }; Counter::Counter(): itsVal(0) {} Counter Counter::operator++() ++itsVal; Counter temp; temp.SetItsVal(itsVal); return temp; } list 10.9

int main() { Counter i; cout << "The value of i is " << i.GetItsVal() << endl; i.Increment(); ++i; Counter a = ++i; cout << "The value of a: " << a.GetItsVal(); cout << " and i: " << i.GetItsVal() << endl; return 0 }

#include <iostream> using namespace std; class Counter { public: Counter(int val); ~Counter(){} int GetItsVal()const { return itsVal; } void SetItsVal(int x) {itsVal = x; } void Increment() { ++itsVal; } Counter operator++ (); private: int itsVal; }; Counter::Counter(): itsVal(0) {} Counter::Counter(int val):itsVal(val) Counter Counter::operator++() ++itsVal; return Counter (itsVal); } list 10.10

int main() { Counter i; cout << "The value of i is " << i.GetItsVal() << endl; i.Increment(); ++i; Counter a = ++i; cout << "The value of a: " << a.GetItsVal(); cout << " and i: " << i.GetItsVal() << endl; return 0; }

#include <iostream> using namespace std; class Counter { public: int GetItsVal()const { return itsVal; } void SetItsVal(int x) {itsVal = x; } void Increment() { ++itsVal; } const Counter& operator++ (); private: int itsVal; }; Counter::Counter(): itsVal(0) {}; const Counter& Counter::operator++() ++itsVal; return *this; } list 10.11

int main() { Counter i; cout << "The value of i is " << i.GetItsVal() << endl; i.Increment(); ++i; Counter a = ++i; cout << "The value of a: " << a.GetItsVal(); cout << " and i: " << i.GetItsVal() << endl; return 0; }

기타 상수형 반환 이유 Counter a = ++++ i; 후치 연산자 중첩 상수형 반환이 아니라면 위의 코드 작성 가능 상수형 반환 시 위의 코드 실행 불능 후치 연산자 중첩 컴파일러는 전치 후치 구분 방법? 후치 표시를 위해 관습적으로 연산자 선언에 정수 매개변수 이용 즉, 정수 매개변수를 이용은 않으나 매개변수가 있으며 후치임을 의미 후치 시 참조자에 의한 반환 불가능, 반드시 값을 반환 Counter a = ++++ i;

#include <iostream> using namespace std; class Counter { public: Counter(int initVal); Counter(const Counter& rhs); ~Counter(){} int GetItsVal()const { return itsVal; } void SetItsVal(int x) {itsVal = x; } const Counter& operator++ (); // 전치 const Counter operator++ (int); // 후치 private: int itsVal; }; list 10.12

Counter::Counter(): itsVal(0) {} Counter::Counter(int initVal): itsVal(initVal) Counter::Counter(const Counter& rhs): itsVal(rhs.itsVal) const Counter& Counter::operator++() { ++itsVal; return *this; } const Counter Counter::operator++(int theFlag) Counter temp(*this); return temp;

int main() { Counter i(3); cout << "The value of i is " << i.GetItsVal() << endl; i++; ++i; Counter a = ++i; cout << "The value of a: " << a.GetItsVal(); cout << " and i: " << i.GetItsVal() << endl; a = i++; return 0; }

이항 연산자의 중첩 a.operator+(b) varThree = varOne.Add( varTwo ); 단항 연산자처럼 만듦 : 단 매개변수를 하나 가진다는 점이 예외 a + b 멤버함수를 이용하는 것과 동일하지만 구문이 훨씬 자연스러움 Counter operator+ (const Counter &); a.operator+(b) Counter varOne, varTwo, varThree ; varThree = varOne.Add( varTwo ); varThree = varOne + varTwo ;

#include <iostream.h> using namespace std; class Counter { public: Counter(); Counter(int initialValue); ~Counter(){} int GetItsVal()const { return itsVal; } void SetItsVal(int x) {itsVal = x; } Counter Add(const Counter &); private: int itsVal; }; Counter::Counter(int initialValue): itsVal(initialValue) {} Counter::Counter(): itsVal(0) Counter Counter::Add(const Counter & rhs) return Counter(itsVal+ rhs.GetItsVal()); } list 10.13

int main() { Counter varOne(2), varTwo(4), varThree; varThree = varOne.Add(varTwo); cout << "varOne: " << varOne.GetItsVal()<< endl; cout << "varTwo: " << varTwo.GetItsVal() << endl; cout << "varThree: " << varThree.GetItsVal() << endl; return 0; }

#include <iostream> using namespace std; class Counter { public: Counter(int initialValue); ~Counter(){} int GetItsVal()const { return itsVal; } void SetItsVal(int x) {itsVal = x; } Counter operator+ (const Counter &); private: int itsVal; }; Counter::Counter(int initialValue): itsVal(initialValue) {} Counter::Counter(): itsVal(0) Counter Counter::operator+ (const Counter & rhs) return Counter(itsVal + rhs.GetItsVal()); } list 10.14

int main() { Counter varOne(2), varTwo(4), varThree; varThree = varOne + varTwo; cout << "varOne: " << varOne.GetItsVal()<< endl; cout << "varTwo: " << varTwo.GetItsVal() << endl; cout << "varThree: " << varThree.GetItsVal() << endl; return 0; }

대입 연산자 CAT catOne(5, 7) ; CAT catTwo(3, 4) ; // …. catTwo = catOne ; 지정하지 않아도 컴파일러가 제공 멤버변수를 각각 할당 멤버변수가 포인터인 경우 깊은 복사 안됨 catTwo 객체의 포인터가 원래 가리키던 메모리 누출 대입연산자를 새로 정의해 대입 시 포인터가 아니라 포인터가 가리키는 값을 직접 복사 자유기억공간 반납 후 재할당 받는 경우 자기 자신인지 반드시 확인 자기 자신을 반납해 버릴 수 있음 CAT catOne(5, 7) ; CAT catTwo(3, 4) ; // …. catTwo = catOne ;

#include <iostream> using namespace std; class CAT { public: int GetAge() const { return *itsAge; } int GetWeight() const { return *itsWeight; } void SetAge(int age) { *itsAge = age; } CAT & operator=(const CAT &); private: int *itsAge; int *itsWeight; }; CAT::CAT() itsAge = new int; itsWeight = new int; *itsAge = 5; *itsWeight = 9; } list 10.15

CAT & CAT::operator=(const CAT & rhs) { if (this == &rhs) return *this; *itsAge = rhs.GetAge(); *itsWeight = rhs.GetWeight(); } int main() CAT frisky; cout << "frisky's age: " << frisky.GetAge() << endl; cout << "Setting frisky to 6...\n"; frisky.SetAge(6); CAT whiskers; cout << "whiskers' age: " << whiskers.GetAge() << endl; cout << "copying frisky to whiskers...\n"; whiskers = frisky; return 0;

#include <iostream> using namespace std; class Eng { public: Eng( int num ); Eng & operator=(const Eng &); private: int itsNum; int *data; }; Eng::Eng( int num ) itsNum = num; data = new int[itsNum]; for( int i=0 ; i<itsNum ; i++ ) data[i] = 0; } list 10.15 심화

Eng & Eng::operator=(const Eng & rhs) { if (this == &rhs) return *this; delete data; itsNum = rhs.itsNum data = new int [itsNum] ; for( int i=0 ; i<itsNum ; i++ ) data[i] = rhs.data[i] ; } int main() Eng classA( 40 ); Eng classTemp( 10 ); … classTemp = classA; classA = classA return 0;

변환 연산자 1 class CAT { public: CAT(int val) ; …. }; 내장된 형의 변수  사용자 정의 클래스 객체 대입 내장된 형의 변수를 매개변수로 가지는 생성자를 통해 지원 class CAT { public: CAT(int val) ; …. }; … int main( ) int a = 5 ; CAT Frisky ; Frisky = a ; }

#include <iostream> using namespace std; class Counter { public: Counter(int val); ~Counter(){} int GetItsVal()const { return itsVal; } void SetItsVal(int x) {itsVal = x; } private: int itsVal; }; Counter::Counter(): itsVal(0) {} Counter::Counter(int val): itsVal(val) int main() int theShort = 5; Counter theCtr = theShort; cout << "theCtr: " << theCtr.GetItsVal() << endl; return 0; } list 10.17

변환 연산자 2 사용자 정의 클래스 객체  내장된 형의 변수 대입 클래스에 추가할 수 있는 변환 연산자 제공 변환 연산자는 반환값을 지정하지 못함 하지만 실제로는 값을 반환

#include <iostream> class Counter { public: Counter(); Counter(int val); ~Counter(){} int GetItsVal()const { return itsVal; } void SetItsVal(int x) {itsVal = x; } operator int (); private: int itsVal; }; Counter::Counter(): itsVal(0) {} Counter::Counter(int val): itsVal(val) Counter::operator unsigned short () return ( int (itsVal) ); } list 10.18

int main() { Counter ctr(5); int theShort = ctr; std::cout << "theShort: " << theShort << std::endl; return 0; }

Hw #3 복소수를 표시하기 위한 class를 제작 현재 복소수 값을 화면에 표시하기 위한 멤버함수를 작성해 보세요 이 class에 operator overloading을 이용하여 복소수의 사칙 연산이 가능하도록 하세요