프로그래밍 공부
작성일
2023. 5. 5. 09:11
작성자
WDmil
728x90

C++에서 operator을 활용하여 비교연산자를 오버로딩하고, 이를 활용해서 Class 안에 있는 모든 변수를 비교연산 해줄 수 있다.

 

보통, 비교연산을 위한 변수가 한개이거나, 모든 변수를 전부 비교해야 할 경우 사용하고, 여러개의 변수를 가지는 Class가 존재하고, 그 변수들 중 한개의 변수만 비교연산이 필요하다면, 그럴때 에는 operator의 사용을 권장하지 않는다.

 

비교연산자 같은 연산자 오버로딩 방식은, 어떠한 변수나 Class의 전체를 비교하거나 연산하는 방식으로 동작해야 하기 때문에 설계방식에서 벗어나기 때문이다.


 

다음은 비교연산자를 오버로딩하여 만든 코드 예시이다.

위 코드에서, 연산자 오버로딩을 활용하여 비교연산을 해줄 수 있는것을 볼 수 있다.

값의 변환을 유도하지 않기 때문에, 혹시나의 상황 또는 코드 자체의 직관성을 높여주기 위해 const 선언을 해주고

bool타입 반환을 해준다.

이 때, friend 선언으로 전역함수 화 시켜 밖에서 함수를 만들고 유도해줄 수 있다.


 

다음은, 메인문에서 구축된 비교연산자를 활용, if문을 동작시키는 코드이다.

위와 같은 코드로 보았을 때 52번째 줄 w1 과 w2의 비교연산은 원래라면 불가능하지만, Won 내부에 operator 선언을 해주었기 때문에 operator방식으로 비교연산자가 성립하여 가능해지는 것 을 볼수있다.


C++에서는 다양한 알고리즘 라이브러리를 지원한다. 이러한 라이브러리는

선언을 통해 사용할 수 있으며, 이중참조 포인터배열의 시작점과 끝, 그리고 sort와 shuffle 연산을 지원한다.

 

바로 위의 코드 이미지에서 sort와 random_shuffle 함수의 사용 예시를 보여주었다.

각각 이중참조 포인터배열의 시작과 끝을 나타내고, ( begin(), end() 를 활용하였다 )  넣어주면, 알아서 랜덤하게 섞어 동작하게 된다.

 

이 중 sort 활용 방법중 람다식 함수 를 사용하여 더 쉽고 간단하게 코드를 캡슐화 할 수 있는데, 다음 코드 예시를 살펴보자.

람다식 함수는 함수의 이름을 지정하지 않고 내부에서만 사용할 간단한 함수를 구축하는 방법이다.

쉽고 간단하게 즉석에서 붙여버릴 수 있음으로 매우 강력한 방법이지만,

 

외부에서 다시 사용이 불가능하다는 단점또한 존재한다.


C++에서 사용할 수 있는 operator중에 첨자 연산자 또한 가능하다. 이는 [] 로 이걸 활용하여 class를 리스트 처럼 만들어서 사용할 수 있다.

일반적인 리스트 연산은 범위값을 벗어났을 때, 쓰래기값이 찍히게된다.

위에서 출력한 arr의 -1과 3은 값을 찍을 수 없지만, 일단 참조가 가능함으로 찍게된다.

 

그러나, Class를 배열처럼 사용하면, 쓰레기값이 찍히면 lsit의 값을 리턴해주는것 이 아니라 어떠한 출력값을 대신해서 나타내줄 수 있음으로, 오류에 대한 연산처리나 컴파일러가 잡아내지 못한 버그를 쉽게 수정할 수 있게 된다.


C++에서 사용할 수 있는 operator중에 () 를 묶는 것으로 함수 처럼 Class를 사용할 수 있다. 이를 Functor이라고 한다. 이렇게 오버로딩을 하는 이유는, 객체를 함수처럼 사용하기 위해서 이다.

 

이렇게 객체를 함수처럼 사용함 으로 써 나타나는 장점은 다음과 같다.

  1. 유연성
    • Class 이기에 함수와 다르게 상태를 유지하면서 호출이 되기 때문에 같은 코드를 다양한 맥락에서 다양한 동작을 수행하는데 사용할 수 있다.
  2. 일반화
  3. 표현력
    • 펑터는 객체로서 표현력을 높이는데 사용된다. 특히, STL과 함께 사용될 경우 함수포인터 보다 코드 가독성이 크게 높아진다.

단점은 다음과 같다.

  1. 오버헤드 빈도가 높아진다.
    • 펑터를 사용하면, 일반적인 함수 포인터 보다 더 많은 오버헤드가 발생한다. 이는 성능이 낮을 수도 있는 임베디드 시스템에서의 성능저하로 이어질 수 있다.
  2. 구현이 복잡하다.
    • 펑터를 작성하는것은 함수포인터보다 훨씬 복잡하다. 이어지는 객체간의 상호작용도 신경써야 하기 때문에, 단순 함수를 호출해야할 경우 펑터를 사용하는것은 설계상 비효율적일 수 있다.

 

쉽게 설명하자면, 원래 함수에는 데이터가 저장이 불가능하나, Class 자체를 하나의 함수처럼 보고 이용하게 되면, 해당 함수가 가지고있는 중간 처리과정의 데이터변수를 호출하여 변경해줄 수 있게된다. 그렇기에 더 효율적인 프로그래밍이 가능해지는것이다.


다음은 코드예시이다.

위와 같이 () 로 묶는것처럼 함수를 호출하여, 해당 Class를 함수처럼 이용이 가능하게 한다.

위와같이, 출력부 함수를 같이 만들어 기입해주었기 때문에, 더 쉽게 class호출이 가능해지는것 이다.

또한, 이러한 방법도 함수 오버로딩의 방법중 하나이기 때문에, 다른 형식지정자를 기입하여, 일반적인 변수가 아닌, class를 참조하고, 이 class 내부의 좌표값 지정 호출방법을 따로 지정하여

 

출력부에 출력부를 넣는 방법으로 출력을 정의해줄 수 있다. ( 쉽게 설명하면. Point라는 class를 지정해주고, 이 class의 생성자가 내부변수를 초기화해준 뒤, Adder 에서 정의된 Point의 함수방식인 45번째 줄이 동작하여, Point 변수 끼리의 덧셈을 호출하고, Point간의 덧셈은 Point 내부에 정의되어 있기 때문에, 타고들어가서 정의된 Point 덧셈방식을 출력하게되는 과정을 도출한다. )

 

순서대로 다시 정리하면

Adder( 덧셈호출 ) -> ( 매개변수 두개 ) [Point A, Point B] -> Adder( Point 형식에 해당되는 오버로딩이 있는지 검사 ) -> Adder( Point 형식에 해당되는 operator를 실행 ) -> Adder(A + B 를 리턴함 ) -> 컴파일러( A + B의 형식을 검사하고 해당되는 operator가 정의되어있는지 확인 ) -> Point( 내부의 덧셈 operator가 선언시에 이미 컴파일러에 전달되어있음 ) -> 해당되는 operator의 연산과정을 도출하고 return을 반환함.

 

위 과정을 진행하여, 65번째 줄의 코드를 다시 정리하면

65번째 줄과 67번째 줄은 같다.


C++에서 형 변환을 하여 operator해줄 수 있다. 다음은 형변환으로. int형태로 데이터를 변환하여 출력하는 방식이다.

위 방법대로 원래는 w는 Won형식이라 Print 에서는 int형으로 받아와서, 출력이 안돼야 정상이다.

그럼에도 Won 내부에 int형식으로 받아올 시, 리턴되는 값을 정의해주었기 때문에 Print가 가능해진다.

 

이러한 방식으로 flaot이나 다른 형 지정자 또한 가능하다.

 

이런 방법을 응용해서,  단 한개의 값만 받아오고 다음값을 배열처럼 참조하여 출력하는 방식도 가능하다.

위와 같은 방식대로, 원래는 한개의 p의 x값의 주소만 가져가게 되나 Class의 같은 형식지정자는 연속된 데이터주소를 가짐으로 배열처럼 값을 도출하여 출력해줄 수 있다.


operator는 new와 delete에도 동작가능하여, 해당동작사항에 오버로딩을 해줄 수 있다.

그러나, 일반적으로 사용하는 방식은 아니고 사용할 일도 거의 없음으로 이러한 방식이 있다는것 만 알고있으면 된다.


C++에는 스마트 포인터 라는 개념이 존재한다. 이는 객체 자신의 자기주소값을 반환해주는 operator를 오버로딩하여, 값의 변환을 쉽게 해줄 수 있는 장점이 있다.

원래라면, num이라는 값은 포인터가 아님으로 연결되는 연산자는 . 이 맞으나, -> 연산자로 자기스스로가 포인터가 아니더라도, 자기스스로의 포인터 재참조가 가능해져서, -> 연산으로 동작을 구현해줄 수 있게되었다.

 

33번줄 34번줄은 각각 37번줄 38번줄과 같다.

728x90