본문 바로가기
42seoul/circle-4

[ CPP02 ] 0. 과제이해하기

by saniii 2022. 7. 30.

 

# Orthodox Canonical Class Form (OCCF)

- 02부터 나오는 새로운 규칙, class를 만들 때 4가지 멤버 함수를 필수적으로 포함해야한다. 

  • Default constructor
  • Copy constructor
  • Copy assignment operator
  • Destructor

 

 

# 복사 생성자 

 

복사에는 얕은 복사와 깊은 복사가 있는데 가장 이해하기 쉬운 예로 메모리를 할당받은 (원본)변수(-> 포인터)를 복사한다고 할 때 얕은 복사는 원본 변수가 가리키고 있는 주소값을 복사해와 같은 메모리를 가리킨다면 깊은 복사는 원본 변수가 할당받은 메모리 크기 만큼 새로 할당 받고 값까지 복사하는 것을 말한다. 얕은 복사는 원본 변수와 복사변수가 같은 값을 출력하며 같은 메모리를 가리키지만 깊은 복사는 같은 값을 출력하지만 원본 변수와 복사 변수가 가리키는 메모리는 다르다. 

 

  • 얕은 복사 (shallow copy)
    • 원본과 복사본이 같은 메모리를 공유하여 복사본을 통해 값을 변경하면 원본도 영향을 받는다. (의도하지 않은 원본 훼손 발생 가능)
  • 깊은 복사 (deep copy)

 

  • 복사 생성자 (copy constructor)
    • 복사 생성자는 객체가 생성될 때 파라미터로 전달받은 클래스 객체를 복사하여 생성되게 한다. 
      • 파라미터로 전달받은 객체는 복사하여 생성하고자 하는 객체와 같은 클래스여야 한다. 
      • 복사 생성자는 클래스에 한개만 선언할 수 있다. 

 

 

 

치환 연산과 복사 생성자의 차이점 알아보기 

 

 

 


 

ex00 

 

fixed point number를 포함하는 클래스를 OCCP를 지켜서 생성하세요

 

  • private
    • int -> fixed point number 값을 저장
    • static const int -> fractional bits를 저장, 항상 8이다.
  • public
    • fpn을 0으로 초기화하는 기본 생성자
    • 복사생성자
    • 연산자 중복 하는 복사 생성자
    • 소멸자
    • int getRawBits( void ) const; -> fixed point value의 값을 반환 
    • void setRawBits( int const raw ); -> fixed point value의 raw값을 설정하는 함수

 


 

 

# 부동 소수점 (floating point number)  고정 소수점 (fixed point number)

위의 내용에 대한 설명은 많은 블로그들에 자세한 설명이 있기 때문에 생략한다. 

https://velog.io/@hidaehyunlee/CPP-02-%EC%A0%95%EC%88%98%EB%B6%80%EB%8F%99%EC%86%8C%EC%88%98%EA%B0%92-%EA%B3%A0%EC%A0%95%EC%86%8C%EC%88%98%EA%B0%92-%EB%B3%80%ED%99%98 

저는 이분의 블로그와 여기서 추천한 블로그글을 통해 이해할 수 있었습니다..ㅎㅎ

 

# fractional bits = 8 -> 고정소수점으로 변환할 때 소수부를 표현하는 bit수를 8로 지정

고정 소수점으로 변환하고자 할 때 8bit가 존재해야하므로 8의 값을 가지는 변수를 하나 저장해놓고 shift 연산자를 사용하여  8비트짜리 공간을 만들고자할 때 사용한다. 

 

 

### 과제에서 주는 예시 42.42라는 숫자를 통해서 어떻게 부동-> 고정 -> 부동 으로 가는지 이해해보자.

 

우선 부동소수점과 고정소수점을 잘 이해했다면 고정소수점은 소수점을 표현할 수 있는 비트수를 지정해놓아서 우리 과제의 경우 8비트로만 소수점을 표현할 수 있다는 것을 알 수 있다. 즉 소수점을 2진수로 표현했을 때 8번째 자리가 넘어가는 수들은 버린다. 

(왜 부동으로 지었냐 진짜... 부동이라하면 고정된 것 같잖아 자꾸;;;;)

 

1. 먼저 생성자로 42.42f를 받을 때 유동소수점 기준으로 저장이 된다.

(여기서 f는 float로 저장하겠다는 의미일 뿐이다.)

2. 여기서 우리는 고정소수점기준으로 표현할. 이진수 표현법상 8개의 소수자리까지 포함하여 int형의 fixed_point에 저장해야한다. 

즉, 예를 들어 이진수상 1010.110011001010 이라는 숫자를 fixed_point에 저장하려면 소수자리 8개는 포함해야 나중에 이 소수를 소수출력할 수 있으므로 (1 << 8) 이나 256을 곱하여 101011001100.1010 을 만든 다음 (roundf로 반올림 하고) fixed_point에 소수점 앞부분인 101011001100(이건 예시로 적은 거라 반올림 하면 마지막 숫자가 변할 수 있음)를 저장하는 것이다.  그리고 나중에 출력할 때 곱했던 만큼 나눠서 1010.11001100의 수를 출력하면 된다. 

 

그럼 42.42의 경우로 보자.

42.42를 2진수로 변환하면 101010 . 01101011 10000101000111101011100001010001111011 

여기서 나중에 소수점으로 표현해야하는 소수점 8비트를 살리기 위해 2^8 을 곱하면 10101001101011.10000101000111101011100001010001111011 이 되고 여기서 소수점을 반올림하면

10101001101100 이 된다. (반올림은 10진수 표현 기준으로 생각하는게 쉬움) 

그럼 fixed_point에 저장되는 수가 이진수 표현법상 10101001101100 이 되는 것이다.

 

그리고 나중에 우리가 고정소수점으로 표현하려면 2^8만큼 나눠서 소수점을 101010 . 01101100 으로 옮긴 다음 출력하면 된다. 

 

 

 

# int getRawBits( void ) const; 함수 선언 뒤 const

 

 

 


ex01

 

고정 소수점을 만들어보세요!

앞에서 만든 클래스를 쓸모있게 만들어봅시다. 

 

다음의 public constructor와 public member func을 클래스에 추가하세오

  • const int를 파라미터로 받는 constructor
    • 파라미터를 받아서 고정 소수점값으로 변환하는 생성자
    • frac_bit는 앞의 문제와 같이 8로 초기화 하세염
  • const float 를 파라미터로 받는 constructor 
    • 파라미터를 받아서 고정 소수점값으로 변환하는 생성자
    • frac_bit는 앞의 문제와 같이 8로 초기화 하세염
  • float toFloat( void ) const;
    • fixed_point(고정소수점) 값을 floatint point 값(부동 소수점) 로 변환한다. 
  • int toInt( void ) const;
    • fixed point 값을 int값으로 변환
  • <<를 오버로딩
    • 고정소수점 수의 유동소수점 표현을 outputstream에 전달해라 

 


 # 연산자 오버로딩

 

c++ 자체에 연산하려는 타입에 따라 이미 오버로딩 되어있지만 내가 새로 만든 클래스의 객체를 연산하기 위해 연산자를 오버로딩할 수 있다. 

  • C++ 언어에 원래 있는 연산자만 중복 가능하다. 
    • 새로운 연산자를 만들어 낼 수 없다. 
      • +, ++ 오버로딩 가능  %% 오버로딩 불가능
  • 연산자 중복은 피연산자의 타입이 다른 연산을 새로 정의할 수 있다. 
  • 연산자 중복으로 피연산자의 개수를 바꿀 수 없다. 
  • 연산자 중복으로 연산의 우선순위를 바꿀 수 없다. 
  • .    .*   ::   ? : (3항 연산자)  이 4가지는 오버로딩할 수 없다. 
  • 연산자 중복은 연산자 함수를 통해서 구현할 수 있는데 
    • 클래스의 멤버함수로 구현하거나
    • 외부 함수로 구현하고 클래스의 friend 함수로 선언할 수 있다.

 

  • 이항 연산자 / +  -  ==   
    • Fixed 클래스에 멤버함수로 +를 오버로딩한 후  Fixed 객체 a, b에 대해  a + b 를 실행하면 컴파일러가  a . + ( b ) 로 변환하여 컴파일한다. 즉, a 객체의 함수+b를 파라미터로 전달하는 것이다. 
  • 단항 연산자 / ++ -- 
    • 단항 연산자는 전위냐, 후위냐 에 따라서 달라진다. 
    • 전위 연산자 / ++a
      • ++a 를 실행하면 컴파일러가 a . ++ ( ) 로 변환하여 컴파일한다. 
      • ++의 파라미터를 void형으로 아무것도 받지 않고 a의 변수를 ++ 한 후 자기 자신을 반환한다. 
    • 후위 연산자 / a++
      •  

 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

'42seoul > circle-4' 카테고리의 다른 글

[ CPP04 ] 0. 과제이해하기  (0) 2022.08.02
[ CPP03 ] 0. 과제이해하기  (0) 2022.08.01
[NetPractice] 01. need to know  (0) 2022.07.31
[ CPP01 ] 0. 과제 이해하기  (0) 2022.07.28
[ NetPractice ] NetAnswer  (0) 2022.07.12

댓글