연산자 다중정의
1. 연산자 다중정의
피연산자의 자료형과 연산자
연산자는 피연산자의 자료형에 따라 적절한 처리절차가 정의되어 있음
동일 연산자라도 자료형에 따라 구체적인 처리방법 상이
(1) 연산자 다중정의
c++에 정의된 연산자를 사용자가 선언한 클래스 객체에 대해 사용할수 있도록 정의
** 주의사항
연산자의 의미를 임의로 바꾸지 않음, 연산자의 고유한 특성 유지
(우선순위, 피연산자의 수, 전위 표기와 후위표기 연산자의 의미 유지)
** 다중정의 대상 주요 연산자
▷ 클래스 객체간 대입 및 이동대입 연산자 : 동적 할당을 받는 포인터를 포함하는 경우 등
▷ 수치형 객체의 산술연산자 다중정의 : 교환법칙 고려
▷ 두 객체를 비교하기 위한 관계 연산자의 다중정의
▷ 스트림 입력 및 출력을 위한 >>, << 연산자
** 다중정의 불가 연산자
▷ 멤버 선택 연산자(.) ex) a.x
▷ 멤버에 대한 포인터 연산자 (.*)
▷ 유효범위 결정 연산자 (::)
▷ 조건 연산자(? :)
** 다중정의 위치
▷ 클래스의 멤버로 정의 : 연산자 구현과정에서 객체의 멤버를 엑세스 할수 있음
▷ 클래스 외부에서 정의 : 객체의 private멤버 직접 사용불가 (private멤버 엑세스 별도 구성)
(2) 단항 연산자의 다중정의
피연산자가 1개, 전위표기법과 후위표기법
▷ 단항연산자의 다중정의 (클래스내 정의)
전위표기법은 객체의 참조를 반환하며, 후위표기법은 클래스의 객체를 반환
ex) Pencils 클래스
① n타스 m자루 연칠의 갯수를 표현하는 class선언, ② 낱개의 수를 1개 증가시키는 전위, 표위표기 ++ 연산자 포함, ③ 연필의 수량을 출력하는 멤버함수 포함
** 행위 (멤버 함수)
** 속성 (데이터 멤버: 메모리 할당을 받아야 하며, 할당된 메모리를 연결하는 포인터)
(3) 이항 연산자의 다중정의
이항연산자 정의
opSymbol: +, -, *, / , &&, || 등의 이항 연산자 기호
객체 자신이 좌측 피연산자, args가 우측 피연산자에 해당됨
a(객체 자신) + b(args)
(4) 스트림 출력 연산자(<<) 다중정의
▷ 스트림 출력 연산자를 정의할 위치
→ 좌측 피연산자인 cout은 Complex2의 객체가 아니며, cout이 속한 ostram클래스를 일반 프로그래머 수정불가
→ 클래스에 속하지 않는 외부 별도 연산자로 정의, << 연산자가 Complex2객체의 private멤버를 엑세스 할수 있도록 friend로 지정
▷ 스트림 출력 연산자를 정의(위치)
2. 대입 및 이동대입 연산자
(1) 대입연산자 (=)
묵시적인 대입연산자 : 우측 피연산자의 데이터 멤버를 좌측 피연산자에 복사
- 객체에 동적 할당된 메모리 포인터가 포함된 경우 의도하지 않은 공유 상태의 문제야기
- 깊은 복사를 할수 있는 대입 연산자를 다중정의할 필요가 있음
(2) 이동대입연산자 (=)
좌측 피연산자에 대입할 우측 피연산자가 rvalue일때 사용
- 대입후 우측 피연산자 불필요 (rvalue의 자원을 이동하게 함)
- 우측 피연산자의 내용을 좌측 피연산자로 이동, 불필요한 복사없어 효율성 증대
(3) 대입 및 이동 대입연산자 활용
(4) std::move 함수의 활용
▷ 두 VecF객체를 교환하는 함수의 구현 (swap )
▷ 인수로 전달되는 객체의 rvalue 참조를 반환
VecF tmp = std::move(v1) v1의 rvalue의 참조를 구하여 tmp의 초기화에 사용 (이동 생성자로 tmp생성)
v1 = std::move(v2) v2의 rvalue 참조를 구하여 v1에 대입 (이동대입 연산자 실행)
(5) []연산자의 다중정의
▷ SafeIntArray 클래스
① 배열처럼 지정된 개수의 int값 저장 ex) SafeIntArray a(10), ② 각각의 값들은 0부터 일련번호를 첨자로 지정하여 엑세스 ex) a[5]=10 (6번째 위치에 10저장), ③ 첨자가 지정된 범위를 벗어날 경우 오류메시지 출력하고 프로그램 종료 ex) cout << a[11]
▷ []연산자
- 배열의 첨자를 지정하는 이항 연산자(피연산자 2개), 피연산자: 배열과 첨자
- 데이터를 저장하기 위해 사용할 []연산자, SafeIntArray a(10), a[5]=10
▷ const 객체를 위한 []연산자 (데이터를 읽기만 할수 있도록 const를 적용한 []연산자 정의)
3. C 스타일 문자열
(1) 문자열 ( Null-terminated string )
- 일반 문자열: 문자열의 크기대로 공간확보, 문자열의 끝에 null문자 ('\0')사용
- 배열이 크기가 명시되지 않으면 배열의 크기 + 1
- 문자열 리터럴 : 메모리에 공간이 만들어지고, 포인터 표시
(2) C스타일 문자열 처리함수
- 헤더파일: #include <cstring>
▷ 문자열 길이 : strlen(포인터), null포인터 미반영
size_t strlen(const char* str); ex) n= strlen("abcde") → n = 5
▷ 문자열 복사 : strcpy(목적지 포인터, 소스포인터)
char* strcpy(char* strDestination, const char* strSource)
▷ 문자열 연결 : strcat(목적지 포인터, 소스포인터)
char* strcat(char* strDestination, const char* strSource)
(3) 새로운 C 문자열 스타일 생성 연습
** 요구사항
-문자열을 저장하되 다중정의된 연산자를 포함하며 실행시 필요에 따라 저장공간을 늘릴수 있음
( char s1[10]; char s2[10]; s1 ="abc" 혹은 s1=s2 오류, s1/s2는 배열의 포인터이므로 복사불가 )
(4) String
- 문자열을 저장하기 위한 c++ 표준 라이브러리 클래스
basic_string<char> (문자를 저장하기 위한 c++의 기본클래스)
- 헤더파일 #include <string>
- 연산자 : [], +, =, +=, ==, !==, >, >=, < , <=, 스트림 입출력(<<, >>)등
- 멤버함수: length, append, find, c_str (cstyle문자열 변환)등
- 함수: stoi, stod, to_string, swap, getline 등 (string을 int, double, 객체변환 등)
4. 자료형 변환
(1) 묵시적 형변환
MyString클래스의 묵시적 형변환
str3 = "Programming"; c스타일 문자열을 MyString객체에 대입하기 위해 컴파일러가 생성자를 참조 MyString으로 묵시적 형변환
(2) 형변환 연산자를 정의하는 위치
▷ 값을 제공하는 송신측 클래스에서 정의 (값을 받는 수신측 클래스 이름으로 연산자 정의)
ex) MyString클래스의 객체를 C스타일 문자열로 변환 (자신은 const로 유지하면서 형변환만 진행)
▷ 값을 제공받는 수신측 클래스에서 정의 (송신측 클래스의 객체를 인수로 받는 1인수 생성자 정의)
ex) MyString(const char* str);
** 송신측 클래스의 private멤버를 엑세스해야하면, 변환대상 송신클래스애서 private멤버 엑세스가능한 조치필요
(3) 생성자를 이용한 묵시적 형변환 금지
- explicit으로 선언된 생성자
- 명시적 형변환을 지정시에는 생성자를 직접 호출하거나 형변환 연산자(static cast)활용