SlideShare a Scribd company logo
11. 연산자 오버로딩




       아꿈사 오전반 C++ 뽀개기 - TCPL
                    2013. 03. 16
클래스에 오버로딩을 통해 연산자를 중복해서 정의 가능
1. 연산자 고유의 의미구조 유지
2. 간략한 표기가 가능
class complex
{
           double re, im;
    public:
           complex(double r, double i) : re(r), im(i) { }
           complex operator+(complex);
           complex operator*(complex);                      연산자를
}                                                           지정 가능

void f()
{
    complex a = complex(1, 3.1);
    complex b = complex(1.2, 2);
    complex c = b;

    a = b + c;
                                                            클래스간
    b = b + c * a;                                          연산 가능
    c = a * b + complex(1, 2);
}
사용자가 동작원리를 정의하는 함수를 선언할 수 있는 경우
+    -    *    /     %     ^                &
|    ~    !    =     <     >                +=
-=   *=   /=   %=    ^=    &=               |=
<<   >>   >>=  <<=   ==    !=               <=
>=   &&   ||   ++    --    ->*              ,
->   []   ()   new   new[] delete           delete[]

사용자 정의 불가능
::   .     .*      ?:    sizeof    typeid

연산자 기호를 새로 정의하는 것은 불가능하지만
함수식 표기를 통해 연산하면 된다
ex) 거듭제곱을 하려면 **은 안되지만 pow()를 사용

연산자 함수의 이름은 operator 뒤에 해당 연산자를 붙인 형식을 사용
ex) operator<< 은 <<의 연산자 함수
이항 연산자 혹은 단항 연산자 사용시 멤버 / 비멤버가 동시에 정의된 상태라면
오버로딩 모호성 해결 규칙을 통해 하나를 선택

class X                                          단항 연산자 @라 가정시
{
          void operator+(int);                   전위형 연산자 @aa는
          X(int);                                aa.operator@()
}                                                operator@(aa)
void operator+(X, X);
void operator+(X, double);                       후위형 연산자 @aa는
void f(X a)                                      aa.operator@(int)
{                                                operator@(aa, int)
           a + 1;   // a.operator+(1)
           1 + a;   // ::operator + (X(1), a);
                                                 이항연산자 @라 가정시
           a + 1.0; // ::operator + (a, 1.0);
}                                                aa@bb는
                                                 aa.operator@(bb)
                                                 operator@(aa, bb)

사용자 정의 연산자를 작성시에는 임의의 가정을 많이 들이면 안 된다
+, =가 있다고 +=를 컴파일러가 정의해 주지는 않음
연산자 함수 규칙

멤버 함수거나, 사용자 정의 타입의 인자를 최소한 하나 받아들이는 형태가 되어야 함
(new와 delete를 재정의하는 경우에는 해당되지 않음)
사용자 정의를 하지 않으면 표현식의 동작원리를 재정의할 수 없다는 뜻
C++은 확장가능하지만 변경가능한 언어는 아닌 것

클래스, 나열자, 네임스페이스 모두 내부 연산자 정의 가능

네임스페이스 안에서 정의된 연산자의 탐색은 피연산자의 타입을 기반으로 이루어진다
ex) 371p 예제
std::string s = “Hello”;
std::cout<<s;             //ostream에서 string을 출력할 수 없다
operator<<(std::cout, s); //내부적으로 네임스페이스를 처리
연산자 함수의 처리 순서
1. 피연산자가 클래스라면 클래스의 멤버로 operator@가 있는지 검색
2. aa@bb의 맥락에 맞춰 operator@선언을 검색
3. aa가 aa1 네임스페이스에 정의된 것이라면 aa1 안에서 operator@ 검색
4. bb가 bb1 네임스페이스에 정의된 것이라면 bb1 안에서 operator@ 검색
5. 오버로딩 모호성 해결 규칙을 사용해 마무리



연산자 함수는 탐색이 수행될때 멤버와 비멤버 함수의 차이가 없다
보통 함수와 구별되는 점
따라서 언제든 기존 클래스 선언을 수정하지 않고 정의 가능
설계시 객체의 표현정보를 건드리는 함수는 최대한 자제
첫번째 인자의 값은 어쩔 수 없이 변경하는 것으로 한정
ex)
+=는 클래스의 멤버로 넣지만
+는 외부에 둔다
새로운 값을 만들어 내기 때문

+=등의 복합형 대입 연산자를 사용하면 +보다 빠르다
+는 두개의 피연산자와 한 개의 연산결과, 총 세개의 객체가 필요
+=는 두개만 필요
임시 객체가 없기 때문에 런타임 효율면에서 우위
타입 변환 연산자

생성자를 통해 타입 변환을 설정하면, 다음 두가지가 불가능하다
1. 사용자 정의 타입으로부터 기본제공 타입으로의 변환 불가능
2. 새로운 클래스로부터 이미 정의된 클래스로의 변환이 불가능

이를 위해 타입 변환 연산자를 사용
클래스 타입을 X라 할때, X에서 T로 바꿔주는 타입 변환 연산자
X::operator T()를 멤버 함수로 넣어두면 해결

타입 변환 연산자는 읽기 동작은 간단하지만,
대입 및 초기화가 다소 복잡할 경우 쓸모있다

하지만 되도록 자제하자
컴파일러가 모호성을 찾아내긴 하지만, 개발자는 까다로워진다
별도의 이름을 가진 함수를 사용해서 해결
프렌드
보통의 클래스 멤버 함수는 선언되면 기본적으로 세가지 성질을 지닌다
1. 그 클래스의 private 멤버에 접근 가능
2. 클래스의 범위 안에 포함
3. 호출하려면 객체가 필요(this 포인터)

멤버 함수가 선언될 경우 1, 2의 성질을 지니지만, 프렌드 함수는 1의 성질만 가진다
class Vector
{
    friend Vector operator*(const Matrix&, const Vector&);
}
class Matrix
{
    friend Vector operator*(const Matrix&, const Vector&);
}
class List
{                                                           클래스 자체를
    friend class List_iterator;                            프렌드로도 가능
}

프렌드 클래스는 서로 긴밀한 관계를 가질 경우에만 사용
프렌드 클래스 규칙
1. 프렌드 클래스의 선언은 프렌드 관계가 맺어질 클래스보다 먼저 위치해야 한다
2. 프렌드 클래스의 정의는 자신을 프렌드로 선언한 클래스를 직접 감싸고 있는
   비클래스 유효 범위에 위치해야 한다

class A {};
namespace N
{
            class B {};
            class C
            {
                          friend class A;   //유효범위 바깥에 있어 될 수 없음
                          friend class B;   //OK
                          friend class D;   //OK
           };
           class D {};
}
프렌드 함수는
1. 외부 유효 범위에 직접 선언
2. 클래스 혹은 클래스의 파생 클래스를 인자로 취하는 형태가 되어야 한다

class X
{
    friend void f();           //클래스 범위 내에 f()가 없다면 무효
    friend void h(const X&);   //인자 타입으로 X가 들어 있어 찾을 수 있다
}

클래스의 내부 정보에 직접 접근하는 함수를 최소화 하고 싶지만
접근용 함수는 가능한 만들고 싶다면 사용

함수 설계의 초점은
멤버, 정적 멤버, 프렌드로 둘 것인가 결정하는 것이 아니라
“내부 정보를 꼭 접근해야 하는가?”
가 되어야 함

일반적으로는 멤버를 선택하도록 하자
멤버 함수는 „객체가 수정될 수 있음‟을 각인시키기 때문에 변화에도 유동적.
크기가 큰 객체에 대한 연산자 오버로딩
참조자 인자를 사용하자
포인터에 적용되는 연산자는 의미를 재정의 할 수 없기 때문
포인터를 사용한 데이터 접근은 비용이 높다

연산자에서 참조자를 반환값으로 할 경우의 메모리 할당 문제는
동일한 객체의 버퍼를 정적 멤버로 사용

버퍼 사용시 할당 문제가 있다면,
데이터를 담는 내부 정보 타입을 준비하고, 타입의 핸들로 정의하는 쪽이 좋다
그러나 이 경우 반환 타입이 참조나 포인터여서는 안 된다
생성자
복사생성자는 같은 타입의 객체로 초기화하는 데도 사용된다
그러나 복사와 초기화는 다르다는 것에 주의
소멸자가 선언되어 있을 경우 특히 중요
소멸자에서 할당된 저장공간을 해제할 경우 생성 / 소멸 / 복사용 함수를 꼭 준비하자



단일 인자 생성자는 암시적 타입 변환 기능을 가지고 있다
그러나 int에 char를 넣는등의 오류의 원인이 되기도 한다
원하지 않는 암시적 타입 변환은 생성자를 explicit로 선언해 막을 수 있다

class String
{
           explicit String(int n);
};
String s1 = „a‟;       //에러
첨자 연산자
operator[] 함수는 클래스 객체에 첨자 연산을 추가할 때 사용
두번째 인자의 타입은 어떤 타입이든 상관없다
따라서 벡터나 연관 배열 같은 것을 쉽게 정의할 수 있음

함수 호출 연산자
operator()() 연산자는 함수와 마찬가지, 오버로딩 가능
호출할 함수가 하나밖에 없는 타입을 정의
어떤 타입에서 주로 사용되는 함수가 한가지인 경우를 대비

유사 함수 객체(function-like object)
() 연산자는 기존의 객체가 함수처럼 동작하게 함으로써 호출문에 객체를 사용
void negate(complex& c) { c = -c;}
void f(vector<complex>& aa, list<complex>& ll)
{
           for_each(aa.begin(), aa.end(), negate); //vector 원소 전부 음수화
}
역참조 연산자
->는 단항 후위 연산자
class Ptr
{
          X* operator->();
}
Ptr의 객체에서 포인터를 쓰듯이 X클래스의 데이터 멤버에 접근이 가능

주의 : ->뒤에 멤버 이름이 있어야 함
void g(Ptr p)
{
           X* q1 = p->;              //에러
           X* q2 = p.operator->();   //ok
}

스마트 포인터를 만들 때 유용
간접 지정을 구현하는 수단으로 ->오버로딩 만큼 깔끔한 것은 없다
반복자와 위임 처리(delegation) 기능에도 사용

-> 연산자는 멤버 함수여야 한다
반환 타입은 포인터 혹은 ->를 적용할 수 있는 클래스 객체여야 한다
증가 연산과 감소 연산
포인터 연산시 범위가 점검되도록 하자

전위형 operator++는 더미 인자를 받지 않도록 선언된다
더미 인자는 후위형 증감 연산자에만 사용

T& operator++();   //전위형
T operator++(int); //후위형
후위형에 쓰인 int 인자는 후위형이라는 것을 표시하기 위한 더미 인자
String 클래스 설계
1. 실제 문자열 데이터 클래스
2. 예외 클래스
3. 읽기와 쓰기 등의 연산자 지원 클래스

생성자 / 소멸자 / 대입 연산자 지원

문자열 데이터 타입을 따로 두고, String은 데이터의 핸들로 구현
데이터가 필요한 경우에만 복사되도록 설계

효율 고민이 없다면 범위 점검 기능이 있는 [], 최적화가 필요하면 범위 접검을 하지 마라

접근용 함수를 인라인으로 둘 경우 각 함수가 데이터 클래스를 모두 참고할 수 있도록 한다
고수의 조언
1. 연산자를 오버로딩할 때는 기존의 용법을 그대로 따라 하는 데 우선적인 초점을 두자.
2. 크기가 큰 피연산자에 대해서는 상수 참조자 타입의 인자를 사용할 것.
3. 연산 결과를 담는 객체가 클 경우에는 반환값 최적화를 고려할 것.
4. 기본 복사 연산자의 동작이 현재의 클래스에 맞으면 그대로 둘 것.
5. 기본 복사 연산자의 동작이 현재의 클래스에 맞지 않으면 오버로딩하든지 private영역에 가
둘 것.
6. 내부 표현 데이터에 접근해야 하는 데는 비멤버 함수보다 멤버 함수가 낫다.
7. 내부 표현 데이터에 접근할 필요가 없는 연산을 구현하는 데는 멤버 함수보다 비멤버 함수가
낫다.
8. 클래스를 지원하는 보조 함수들은 네임스페이스를 써서 서로 관련지어 주자.
9. 대칭형 연산자에 대해서는 비멤버 함수를 사용하자.
10. 다차원 배열의 첨자 연산은 () 연산자로 구현하자.
11. '크기 표시' 인자 하나만을 받아들이는 생성자는 반드시 명시호출 생성자로 만들자.
12. 특별한 경우가 아닌 이상 여러분이 만든 문자열 클래스보다는 표준 string이 훨씬 탓다.
13. 암시적 타입변환이 끼어들 수 있는 부분에 각별히 촉각을 세우도록.
14. 좌변값을 좌변 피연산자로 사용하는 연산자를 만들 때는 멤버함수를 사용하자.
Q&A

More Related Content

What's hot

Javascript 완벽 가이드 정리
Javascript 완벽 가이드 정리Javascript 완벽 가이드 정리
Javascript 완벽 가이드 정리
ETRIBE_STG
 
나에 첫번째 자바8 람다식 지앤선
나에 첫번째 자바8 람다식   지앤선나에 첫번째 자바8 람다식   지앤선
나에 첫번째 자바8 람다식 지앤선
daewon jeong
 

What's hot (20)

Start IoT with JavaScript - 4.객체1
Start IoT with JavaScript - 4.객체1Start IoT with JavaScript - 4.객체1
Start IoT with JavaScript - 4.객체1
 
Reflect package 사용하기
Reflect package 사용하기Reflect package 사용하기
Reflect package 사용하기
 
Haskell study 4
Haskell study 4Haskell study 4
Haskell study 4
 
Javascript 완벽 가이드 정리
Javascript 완벽 가이드 정리Javascript 완벽 가이드 정리
Javascript 완벽 가이드 정리
 
Start IoT with JavaScript - 2.연산자
Start IoT with JavaScript - 2.연산자Start IoT with JavaScript - 2.연산자
Start IoT with JavaScript - 2.연산자
 
Javascript introduction, dynamic data type, operator
Javascript introduction, dynamic data type, operatorJavascript introduction, dynamic data type, operator
Javascript introduction, dynamic data type, operator
 
Haskell study 15
Haskell study 15Haskell study 15
Haskell study 15
 
스파르탄스터디 E04 Javascript 객체지향, 함수형 프로그래밍
스파르탄스터디 E04 Javascript 객체지향, 함수형 프로그래밍스파르탄스터디 E04 Javascript 객체지향, 함수형 프로그래밍
스파르탄스터디 E04 Javascript 객체지향, 함수형 프로그래밍
 
[D2 COMMUNITY] ECMAScript 2015 S67 seminar - 1. primitive
[D2 COMMUNITY] ECMAScript 2015 S67 seminar - 1. primitive[D2 COMMUNITY] ECMAScript 2015 S67 seminar - 1. primitive
[D2 COMMUNITY] ECMAScript 2015 S67 seminar - 1. primitive
 
Haskell study 14
Haskell study 14Haskell study 14
Haskell study 14
 
이것이 자바다 Chap.11 기본 API 클래스(java)(KOR)
이것이 자바다 Chap.11 기본 API 클래스(java)(KOR)이것이 자바다 Chap.11 기본 API 클래스(java)(KOR)
이것이 자바다 Chap.11 기본 API 클래스(java)(KOR)
 
Haskell study 5
Haskell study 5Haskell study 5
Haskell study 5
 
동작 파라미터와 람다 In java 8
동작 파라미터와 람다 In java 8동작 파라미터와 람다 In java 8
동작 파라미터와 람다 In java 8
 
Javascript 함수(function) 개념, 호출패턴, this, prototype, scope
Javascript 함수(function) 개념, 호출패턴, this, prototype, scopeJavascript 함수(function) 개념, 호출패턴, this, prototype, scope
Javascript 함수(function) 개념, 호출패턴, this, prototype, scope
 
Lua 문법 -함수
Lua 문법 -함수Lua 문법 -함수
Lua 문법 -함수
 
나에 첫번째 자바8 람다식 지앤선
나에 첫번째 자바8 람다식   지앤선나에 첫번째 자바8 람다식   지앤선
나에 첫번째 자바8 람다식 지앤선
 
Haskell study 10
Haskell study 10Haskell study 10
Haskell study 10
 
Lua 문법
Lua 문법Lua 문법
Lua 문법
 
이것이 자바다 Chap. 6 클래스(CLASS)(KOR)
이것이 자바다 Chap. 6 클래스(CLASS)(KOR)이것이 자바다 Chap. 6 클래스(CLASS)(KOR)
이것이 자바다 Chap. 6 클래스(CLASS)(KOR)
 
파이썬 함수 이해하기
파이썬 함수 이해하기 파이썬 함수 이해하기
파이썬 함수 이해하기
 

Similar to [아꿈사] The C++ Programming Language 11장 연산자 오버로딩

파이썬+주요+용어+정리 20160304
파이썬+주요+용어+정리 20160304파이썬+주요+용어+정리 20160304
파이썬+주요+용어+정리 20160304
Yong Joon Moon
 
NHNNEXT 개경프14 Subway Rocket Team Study 3rd C++
NHNNEXT 개경프14 Subway Rocket Team Study 3rd C++NHNNEXT 개경프14 Subway Rocket Team Study 3rd C++
NHNNEXT 개경프14 Subway Rocket Team Study 3rd C++
Min-soo Park
 
이펙티브 C++ 공부
이펙티브 C++ 공부이펙티브 C++ 공부
이펙티브 C++ 공부
quxn6
 
The c++ programming language 10장 클래스 발표
The c++ programming language 10장 클래스 발표The c++ programming language 10장 클래스 발표
The c++ programming language 10장 클래스 발표
재정 이
 

Similar to [아꿈사] The C++ Programming Language 11장 연산자 오버로딩 (20)

파이썬+주요+용어+정리 20160304
파이썬+주요+용어+정리 20160304파이썬+주요+용어+정리 20160304
파이썬+주요+용어+정리 20160304
 
Javascript - Function
Javascript - FunctionJavascript - Function
Javascript - Function
 
Java jungsuk3 ch14_lambda_stream
Java jungsuk3 ch14_lambda_streamJava jungsuk3 ch14_lambda_stream
Java jungsuk3 ch14_lambda_stream
 
강의자료3
강의자료3강의자료3
강의자료3
 
Functional programming
Functional programmingFunctional programming
Functional programming
 
함수적 사고 2장
함수적 사고 2장함수적 사고 2장
함수적 사고 2장
 
자바8 람다식 소개
자바8 람다식 소개자바8 람다식 소개
자바8 람다식 소개
 
스칼라와 스파크 영혼의 듀오
스칼라와 스파크 영혼의 듀오스칼라와 스파크 영혼의 듀오
스칼라와 스파크 영혼의 듀오
 
NHNNEXT 개경프14 Subway Rocket Team Study 3rd C++
NHNNEXT 개경프14 Subway Rocket Team Study 3rd C++NHNNEXT 개경프14 Subway Rocket Team Study 3rd C++
NHNNEXT 개경프14 Subway Rocket Team Study 3rd C++
 
STL study (skyLab)
STL study (skyLab)STL study (skyLab)
STL study (skyLab)
 
강의자료4
강의자료4강의자료4
강의자료4
 
프론트엔드스터디 E04 js function
프론트엔드스터디 E04 js function프론트엔드스터디 E04 js function
프론트엔드스터디 E04 js function
 
이펙티브 C++ 스터디
이펙티브 C++ 스터디이펙티브 C++ 스터디
이펙티브 C++ 스터디
 
Changes in c++0x
Changes in c++0xChanges in c++0x
Changes in c++0x
 
파이썬 기초
파이썬 기초 파이썬 기초
파이썬 기초
 
포트폴리오에서 사용한 모던 C++
포트폴리오에서 사용한 모던 C++포트폴리오에서 사용한 모던 C++
포트폴리오에서 사용한 모던 C++
 
2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)
2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)
2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)
 
파이썬 namespace Binding 이해하기
파이썬 namespace Binding 이해하기 파이썬 namespace Binding 이해하기
파이썬 namespace Binding 이해하기
 
이펙티브 C++ 공부
이펙티브 C++ 공부이펙티브 C++ 공부
이펙티브 C++ 공부
 
The c++ programming language 10장 클래스 발표
The c++ programming language 10장 클래스 발표The c++ programming language 10장 클래스 발표
The c++ programming language 10장 클래스 발표
 

More from 해강

[16.04.12] 플레이어의 기억에 남을 인상적인 캐릭터를 제작하는 5가지 주제 - Self
[16.04.12] 플레이어의 기억에 남을 인상적인 캐릭터를 제작하는 5가지 주제 - Self[16.04.12] 플레이어의 기억에 남을 인상적인 캐릭터를 제작하는 5가지 주제 - Self
[16.04.12] 플레이어의 기억에 남을 인상적인 캐릭터를 제작하는 5가지 주제 - Self
해강
 
[15.06.20] 네가 누구든, 내가 뭘하든 - DevRookie
[15.06.20] 네가 누구든, 내가 뭘하든 - DevRookie[15.06.20] 네가 누구든, 내가 뭘하든 - DevRookie
[15.06.20] 네가 누구든, 내가 뭘하든 - DevRookie
해강
 
[15.02.14] 진짜로땜빵하라하시면해야겠지만할시간도없고아무생각도없을때면어쩌면좋지라고소리쳐봤자아무도대답안해줄꺼고어쩔수없이이렇게저렇게어4신...
[15.02.14] 진짜로땜빵하라하시면해야겠지만할시간도없고아무생각도없을때면어쩌면좋지라고소리쳐봤자아무도대답안해줄꺼고어쩔수없이이렇게저렇게어4신...[15.02.14] 진짜로땜빵하라하시면해야겠지만할시간도없고아무생각도없을때면어쩌면좋지라고소리쳐봤자아무도대답안해줄꺼고어쩔수없이이렇게저렇게어4신...
[15.02.14] 진짜로땜빵하라하시면해야겠지만할시간도없고아무생각도없을때면어쩌면좋지라고소리쳐봤자아무도대답안해줄꺼고어쩔수없이이렇게저렇게어4신...
해강
 
[14.06.28] 이 구역의 프로그래머는 나야(devrookie - 공개용)
[14.06.28]  이 구역의 프로그래머는 나야(devrookie - 공개용)[14.06.28]  이 구역의 프로그래머는 나야(devrookie - 공개용)
[14.06.28] 이 구역의 프로그래머는 나야(devrookie - 공개용)
해강
 
[Shader study] Color control (2014.05.12)
[Shader study] Color control (2014.05.12)[Shader study] Color control (2014.05.12)
[Shader study] Color control (2014.05.12)
해강
 
[Dev rookie] 이상적인 게임에 관하여(13.11.30)
[Dev rookie] 이상적인 게임에 관하여(13.11.30)[Dev rookie] 이상적인 게임에 관하여(13.11.30)
[Dev rookie] 이상적인 게임에 관하여(13.11.30)
해강
 
[Softmax] 유익한 무엇에 관하여(13.09.27)
[Softmax] 유익한 무엇에 관하여(13.09.27)[Softmax] 유익한 무엇에 관하여(13.09.27)
[Softmax] 유익한 무엇에 관하여(13.09.27)
해강
 

More from 해강 (20)

[16.04.12] 플레이어의 기억에 남을 인상적인 캐릭터를 제작하는 5가지 주제 - Self
[16.04.12] 플레이어의 기억에 남을 인상적인 캐릭터를 제작하는 5가지 주제 - Self[16.04.12] 플레이어의 기억에 남을 인상적인 캐릭터를 제작하는 5가지 주제 - Self
[16.04.12] 플레이어의 기억에 남을 인상적인 캐릭터를 제작하는 5가지 주제 - Self
 
[15.06.20] 네가 누구든, 내가 뭘하든 - DevRookie
[15.06.20] 네가 누구든, 내가 뭘하든 - DevRookie[15.06.20] 네가 누구든, 내가 뭘하든 - DevRookie
[15.06.20] 네가 누구든, 내가 뭘하든 - DevRookie
 
[15.02.14] 진짜로땜빵하라하시면해야겠지만할시간도없고아무생각도없을때면어쩌면좋지라고소리쳐봤자아무도대답안해줄꺼고어쩔수없이이렇게저렇게어4신...
[15.02.14] 진짜로땜빵하라하시면해야겠지만할시간도없고아무생각도없을때면어쩌면좋지라고소리쳐봤자아무도대답안해줄꺼고어쩔수없이이렇게저렇게어4신...[15.02.14] 진짜로땜빵하라하시면해야겠지만할시간도없고아무생각도없을때면어쩌면좋지라고소리쳐봤자아무도대답안해줄꺼고어쩔수없이이렇게저렇게어4신...
[15.02.14] 진짜로땜빵하라하시면해야겠지만할시간도없고아무생각도없을때면어쩌면좋지라고소리쳐봤자아무도대답안해줄꺼고어쩔수없이이렇게저렇게어4신...
 
[14.12.27] 종횡사해2014(DevRookie)
[14.12.27] 종횡사해2014(DevRookie)[14.12.27] 종횡사해2014(DevRookie)
[14.12.27] 종횡사해2014(DevRookie)
 
[14.12.08] 행렬대수(ShaderStudy)
[14.12.08] 행렬대수(ShaderStudy)[14.12.08] 행렬대수(ShaderStudy)
[14.12.08] 행렬대수(ShaderStudy)
 
[14.10.21] Far Cry and DX9 번역(shaderstudy)
[14.10.21] Far Cry and DX9 번역(shaderstudy)[14.10.21] Far Cry and DX9 번역(shaderstudy)
[14.10.21] Far Cry and DX9 번역(shaderstudy)
 
[14.10.20] 아! 그거...모르겠습니다 - TLS(devrookie)
[14.10.20] 아! 그거...모르겠습니다 - TLS(devrookie)[14.10.20] 아! 그거...모르겠습니다 - TLS(devrookie)
[14.10.20] 아! 그거...모르겠습니다 - TLS(devrookie)
 
[14.10.10] TressFX 번역(self)
[14.10.10] TressFX 번역(self)[14.10.10] TressFX 번역(self)
[14.10.10] TressFX 번역(self)
 
[14.09.01] dynamic lighting in god of war3(shader study)
[14.09.01] dynamic lighting in god of war3(shader study)[14.09.01] dynamic lighting in god of war3(shader study)
[14.09.01] dynamic lighting in god of war3(shader study)
 
[14.06.28] 이 구역의 프로그래머는 나야(devrookie - 공개용)
[14.06.28]  이 구역의 프로그래머는 나야(devrookie - 공개용)[14.06.28]  이 구역의 프로그래머는 나야(devrookie - 공개용)
[14.06.28] 이 구역의 프로그래머는 나야(devrookie - 공개용)
 
[Shader study] the rendering technology of lords of the fallen - 발표메모(14.06.23)
[Shader study] the rendering technology of lords of the fallen - 발표메모(14.06.23)[Shader study] the rendering technology of lords of the fallen - 발표메모(14.06.23)
[Shader study] the rendering technology of lords of the fallen - 발표메모(14.06.23)
 
[Shader study] Lighting Killzone : Shadow Fall - 발표메모(13.10.14)
[Shader study] Lighting Killzone : Shadow Fall - 발표메모(13.10.14)[Shader study] Lighting Killzone : Shadow Fall - 발표메모(13.10.14)
[Shader study] Lighting Killzone : Shadow Fall - 발표메모(13.10.14)
 
[Shader study] Color control (2014.05.12)
[Shader study] Color control (2014.05.12)[Shader study] Color control (2014.05.12)
[Shader study] Color control (2014.05.12)
 
[Dev rookie] Omnibus Me (2014.01.11)
[Dev rookie] Omnibus Me (2014.01.11)[Dev rookie] Omnibus Me (2014.01.11)
[Dev rookie] Omnibus Me (2014.01.11)
 
[Shader study]Shadow Map Silhouette Revectorization(2014.01.06)
[Shader study]Shadow Map Silhouette Revectorization(2014.01.06)[Shader study]Shadow Map Silhouette Revectorization(2014.01.06)
[Shader study]Shadow Map Silhouette Revectorization(2014.01.06)
 
[Dev rookie]사망유희2013(13.12.21)
[Dev rookie]사망유희2013(13.12.21)[Dev rookie]사망유희2013(13.12.21)
[Dev rookie]사망유희2013(13.12.21)
 
[Dev rookie] 이상적인 게임에 관하여(13.11.30)
[Dev rookie] 이상적인 게임에 관하여(13.11.30)[Dev rookie] 이상적인 게임에 관하여(13.11.30)
[Dev rookie] 이상적인 게임에 관하여(13.11.30)
 
[Dev rookie] 어디로 가야 하나요(13.10.05)
[Dev rookie] 어디로 가야 하나요(13.10.05)[Dev rookie] 어디로 가야 하나요(13.10.05)
[Dev rookie] 어디로 가야 하나요(13.10.05)
 
[Softmax] 유익한 무엇에 관하여(13.09.27)
[Softmax] 유익한 무엇에 관하여(13.09.27)[Softmax] 유익한 무엇에 관하여(13.09.27)
[Softmax] 유익한 무엇에 관하여(13.09.27)
 
[Dev rookie] 나는 네가 무엇을 하고 있는지 알고 있다(13.08.24)
[Dev rookie] 나는 네가 무엇을 하고 있는지 알고 있다(13.08.24)[Dev rookie] 나는 네가 무엇을 하고 있는지 알고 있다(13.08.24)
[Dev rookie] 나는 네가 무엇을 하고 있는지 알고 있다(13.08.24)
 

[아꿈사] The C++ Programming Language 11장 연산자 오버로딩

  • 1. 11. 연산자 오버로딩 아꿈사 오전반 C++ 뽀개기 - TCPL 2013. 03. 16
  • 2. 클래스에 오버로딩을 통해 연산자를 중복해서 정의 가능 1. 연산자 고유의 의미구조 유지 2. 간략한 표기가 가능 class complex { double re, im; public: complex(double r, double i) : re(r), im(i) { } complex operator+(complex); complex operator*(complex); 연산자를 } 지정 가능 void f() { complex a = complex(1, 3.1); complex b = complex(1.2, 2); complex c = b; a = b + c; 클래스간 b = b + c * a; 연산 가능 c = a * b + complex(1, 2); }
  • 3. 사용자가 동작원리를 정의하는 함수를 선언할 수 있는 경우 + - * / % ^ & | ~ ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= && || ++ -- ->* , -> [] () new new[] delete delete[] 사용자 정의 불가능 :: . .* ?: sizeof typeid 연산자 기호를 새로 정의하는 것은 불가능하지만 함수식 표기를 통해 연산하면 된다 ex) 거듭제곱을 하려면 **은 안되지만 pow()를 사용 연산자 함수의 이름은 operator 뒤에 해당 연산자를 붙인 형식을 사용 ex) operator<< 은 <<의 연산자 함수
  • 4. 이항 연산자 혹은 단항 연산자 사용시 멤버 / 비멤버가 동시에 정의된 상태라면 오버로딩 모호성 해결 규칙을 통해 하나를 선택 class X 단항 연산자 @라 가정시 { void operator+(int); 전위형 연산자 @aa는 X(int); aa.operator@() } operator@(aa) void operator+(X, X); void operator+(X, double); 후위형 연산자 @aa는 void f(X a) aa.operator@(int) { operator@(aa, int) a + 1; // a.operator+(1) 1 + a; // ::operator + (X(1), a); 이항연산자 @라 가정시 a + 1.0; // ::operator + (a, 1.0); } aa@bb는 aa.operator@(bb) operator@(aa, bb) 사용자 정의 연산자를 작성시에는 임의의 가정을 많이 들이면 안 된다 +, =가 있다고 +=를 컴파일러가 정의해 주지는 않음
  • 5. 연산자 함수 규칙 멤버 함수거나, 사용자 정의 타입의 인자를 최소한 하나 받아들이는 형태가 되어야 함 (new와 delete를 재정의하는 경우에는 해당되지 않음) 사용자 정의를 하지 않으면 표현식의 동작원리를 재정의할 수 없다는 뜻 C++은 확장가능하지만 변경가능한 언어는 아닌 것 클래스, 나열자, 네임스페이스 모두 내부 연산자 정의 가능 네임스페이스 안에서 정의된 연산자의 탐색은 피연산자의 타입을 기반으로 이루어진다 ex) 371p 예제 std::string s = “Hello”; std::cout<<s; //ostream에서 string을 출력할 수 없다 operator<<(std::cout, s); //내부적으로 네임스페이스를 처리
  • 6. 연산자 함수의 처리 순서 1. 피연산자가 클래스라면 클래스의 멤버로 operator@가 있는지 검색 2. aa@bb의 맥락에 맞춰 operator@선언을 검색 3. aa가 aa1 네임스페이스에 정의된 것이라면 aa1 안에서 operator@ 검색 4. bb가 bb1 네임스페이스에 정의된 것이라면 bb1 안에서 operator@ 검색 5. 오버로딩 모호성 해결 규칙을 사용해 마무리 연산자 함수는 탐색이 수행될때 멤버와 비멤버 함수의 차이가 없다 보통 함수와 구별되는 점 따라서 언제든 기존 클래스 선언을 수정하지 않고 정의 가능
  • 7. 설계시 객체의 표현정보를 건드리는 함수는 최대한 자제 첫번째 인자의 값은 어쩔 수 없이 변경하는 것으로 한정 ex) +=는 클래스의 멤버로 넣지만 +는 외부에 둔다 새로운 값을 만들어 내기 때문 +=등의 복합형 대입 연산자를 사용하면 +보다 빠르다 +는 두개의 피연산자와 한 개의 연산결과, 총 세개의 객체가 필요 +=는 두개만 필요 임시 객체가 없기 때문에 런타임 효율면에서 우위
  • 8. 타입 변환 연산자 생성자를 통해 타입 변환을 설정하면, 다음 두가지가 불가능하다 1. 사용자 정의 타입으로부터 기본제공 타입으로의 변환 불가능 2. 새로운 클래스로부터 이미 정의된 클래스로의 변환이 불가능 이를 위해 타입 변환 연산자를 사용 클래스 타입을 X라 할때, X에서 T로 바꿔주는 타입 변환 연산자 X::operator T()를 멤버 함수로 넣어두면 해결 타입 변환 연산자는 읽기 동작은 간단하지만, 대입 및 초기화가 다소 복잡할 경우 쓸모있다 하지만 되도록 자제하자 컴파일러가 모호성을 찾아내긴 하지만, 개발자는 까다로워진다 별도의 이름을 가진 함수를 사용해서 해결
  • 9. 프렌드 보통의 클래스 멤버 함수는 선언되면 기본적으로 세가지 성질을 지닌다 1. 그 클래스의 private 멤버에 접근 가능 2. 클래스의 범위 안에 포함 3. 호출하려면 객체가 필요(this 포인터) 멤버 함수가 선언될 경우 1, 2의 성질을 지니지만, 프렌드 함수는 1의 성질만 가진다 class Vector { friend Vector operator*(const Matrix&, const Vector&); } class Matrix { friend Vector operator*(const Matrix&, const Vector&); } class List { 클래스 자체를 friend class List_iterator; 프렌드로도 가능 } 프렌드 클래스는 서로 긴밀한 관계를 가질 경우에만 사용
  • 10. 프렌드 클래스 규칙 1. 프렌드 클래스의 선언은 프렌드 관계가 맺어질 클래스보다 먼저 위치해야 한다 2. 프렌드 클래스의 정의는 자신을 프렌드로 선언한 클래스를 직접 감싸고 있는 비클래스 유효 범위에 위치해야 한다 class A {}; namespace N { class B {}; class C { friend class A; //유효범위 바깥에 있어 될 수 없음 friend class B; //OK friend class D; //OK }; class D {}; }
  • 11. 프렌드 함수는 1. 외부 유효 범위에 직접 선언 2. 클래스 혹은 클래스의 파생 클래스를 인자로 취하는 형태가 되어야 한다 class X { friend void f(); //클래스 범위 내에 f()가 없다면 무효 friend void h(const X&); //인자 타입으로 X가 들어 있어 찾을 수 있다 } 클래스의 내부 정보에 직접 접근하는 함수를 최소화 하고 싶지만 접근용 함수는 가능한 만들고 싶다면 사용 함수 설계의 초점은 멤버, 정적 멤버, 프렌드로 둘 것인가 결정하는 것이 아니라 “내부 정보를 꼭 접근해야 하는가?” 가 되어야 함 일반적으로는 멤버를 선택하도록 하자 멤버 함수는 „객체가 수정될 수 있음‟을 각인시키기 때문에 변화에도 유동적.
  • 12. 크기가 큰 객체에 대한 연산자 오버로딩 참조자 인자를 사용하자 포인터에 적용되는 연산자는 의미를 재정의 할 수 없기 때문 포인터를 사용한 데이터 접근은 비용이 높다 연산자에서 참조자를 반환값으로 할 경우의 메모리 할당 문제는 동일한 객체의 버퍼를 정적 멤버로 사용 버퍼 사용시 할당 문제가 있다면, 데이터를 담는 내부 정보 타입을 준비하고, 타입의 핸들로 정의하는 쪽이 좋다 그러나 이 경우 반환 타입이 참조나 포인터여서는 안 된다
  • 13. 생성자 복사생성자는 같은 타입의 객체로 초기화하는 데도 사용된다 그러나 복사와 초기화는 다르다는 것에 주의 소멸자가 선언되어 있을 경우 특히 중요 소멸자에서 할당된 저장공간을 해제할 경우 생성 / 소멸 / 복사용 함수를 꼭 준비하자 단일 인자 생성자는 암시적 타입 변환 기능을 가지고 있다 그러나 int에 char를 넣는등의 오류의 원인이 되기도 한다 원하지 않는 암시적 타입 변환은 생성자를 explicit로 선언해 막을 수 있다 class String { explicit String(int n); }; String s1 = „a‟; //에러
  • 14. 첨자 연산자 operator[] 함수는 클래스 객체에 첨자 연산을 추가할 때 사용 두번째 인자의 타입은 어떤 타입이든 상관없다 따라서 벡터나 연관 배열 같은 것을 쉽게 정의할 수 있음 함수 호출 연산자 operator()() 연산자는 함수와 마찬가지, 오버로딩 가능 호출할 함수가 하나밖에 없는 타입을 정의 어떤 타입에서 주로 사용되는 함수가 한가지인 경우를 대비 유사 함수 객체(function-like object) () 연산자는 기존의 객체가 함수처럼 동작하게 함으로써 호출문에 객체를 사용 void negate(complex& c) { c = -c;} void f(vector<complex>& aa, list<complex>& ll) { for_each(aa.begin(), aa.end(), negate); //vector 원소 전부 음수화 }
  • 15. 역참조 연산자 ->는 단항 후위 연산자 class Ptr { X* operator->(); } Ptr의 객체에서 포인터를 쓰듯이 X클래스의 데이터 멤버에 접근이 가능 주의 : ->뒤에 멤버 이름이 있어야 함 void g(Ptr p) { X* q1 = p->; //에러 X* q2 = p.operator->(); //ok } 스마트 포인터를 만들 때 유용 간접 지정을 구현하는 수단으로 ->오버로딩 만큼 깔끔한 것은 없다 반복자와 위임 처리(delegation) 기능에도 사용 -> 연산자는 멤버 함수여야 한다 반환 타입은 포인터 혹은 ->를 적용할 수 있는 클래스 객체여야 한다
  • 16. 증가 연산과 감소 연산 포인터 연산시 범위가 점검되도록 하자 전위형 operator++는 더미 인자를 받지 않도록 선언된다 더미 인자는 후위형 증감 연산자에만 사용 T& operator++(); //전위형 T operator++(int); //후위형 후위형에 쓰인 int 인자는 후위형이라는 것을 표시하기 위한 더미 인자
  • 17. String 클래스 설계 1. 실제 문자열 데이터 클래스 2. 예외 클래스 3. 읽기와 쓰기 등의 연산자 지원 클래스 생성자 / 소멸자 / 대입 연산자 지원 문자열 데이터 타입을 따로 두고, String은 데이터의 핸들로 구현 데이터가 필요한 경우에만 복사되도록 설계 효율 고민이 없다면 범위 점검 기능이 있는 [], 최적화가 필요하면 범위 접검을 하지 마라 접근용 함수를 인라인으로 둘 경우 각 함수가 데이터 클래스를 모두 참고할 수 있도록 한다
  • 18. 고수의 조언 1. 연산자를 오버로딩할 때는 기존의 용법을 그대로 따라 하는 데 우선적인 초점을 두자. 2. 크기가 큰 피연산자에 대해서는 상수 참조자 타입의 인자를 사용할 것. 3. 연산 결과를 담는 객체가 클 경우에는 반환값 최적화를 고려할 것. 4. 기본 복사 연산자의 동작이 현재의 클래스에 맞으면 그대로 둘 것. 5. 기본 복사 연산자의 동작이 현재의 클래스에 맞지 않으면 오버로딩하든지 private영역에 가 둘 것. 6. 내부 표현 데이터에 접근해야 하는 데는 비멤버 함수보다 멤버 함수가 낫다. 7. 내부 표현 데이터에 접근할 필요가 없는 연산을 구현하는 데는 멤버 함수보다 비멤버 함수가 낫다. 8. 클래스를 지원하는 보조 함수들은 네임스페이스를 써서 서로 관련지어 주자. 9. 대칭형 연산자에 대해서는 비멤버 함수를 사용하자. 10. 다차원 배열의 첨자 연산은 () 연산자로 구현하자. 11. '크기 표시' 인자 하나만을 받아들이는 생성자는 반드시 명시호출 생성자로 만들자. 12. 특별한 경우가 아닌 이상 여러분이 만든 문자열 클래스보다는 표준 string이 훨씬 탓다. 13. 암시적 타입변환이 끼어들 수 있는 부분에 각별히 촉각을 세우도록. 14. 좌변값을 좌변 피연산자로 사용하는 연산자를 만들 때는 멤버함수를 사용하자.
  • 19. Q&A