Orthodox 규정을 따르면서 개발할 것
(아래 네 가지 형태를 명시적으로 정의하여 선언할 것)
1. 기본 생성자
2. 복사 생성자
3. 복사 대입 연산자
4. 소멸자
class A
{
A();
~A();
A(const A &a);
A &operator=(const A &a);
};
같은 클래스 타입의 객체에 대한 참조를 인자로 전달받아, 그 참조를 가지고 자신을 초기화하는 방법
A::A(const A &a) {
*this = a; // 오버로딩된 할당 연산자 호출
}
A origin; // 기본 생성자 호출
A copied(origin); // 복사 생성자 호출
대입(할당) 연산자 오버로딩
기존 대입 연산자(=
)를 재정의
operator
키워드와 연산자(=
)를 묶어서 함수의 이름을 정의A &A::operator=(const A &a) {
// 값 복사 실행
return (*this);
}
A a1; // 기본 생성자 호출
A a2 = a1; // 복사 생성자 호출
A a3; // 기본 생성자 호출
a3 = a2; // 복사 대입 연산자 사용
깊은 복사를 하는 이유
- 생성자 내에서 동적 할당을 하는 경우, 객체 소멸 과정에서 중복으로 delete를 하게 됨
- 원래 가리키던 메모리의 포인터를 삭제하지 않고 잃어버리게 되어 메모리 누수 발생
고정 소수점, 부동 소수점 등 구현은 뒤에서 하기 때문에 여기서는 클래스를 OCF에 맞춰서 생성하기만 하면 됨
Fixed
클래스integer
멤버 변수: 고정 소수점 숫자static constant integer
멤버 변수: 소수부를 표현할 비트 수. 항상 8
int getRawBits( void ) const;
: 고정 소수점 값의 raw 값 리턴void setRawBits( int const raw );
: 고정 소수점 수의 raw 값 설정int main(void) {
Fixed a;
Fixed b(a);
Fixed c;
c = b;
std::cout << a.getRawBits() << std::endl;
std::cout << b.getRawBits() << std::endl;
std::cout << c.getRawBits() << std::endl;
return (0);
}
$> ./a.out
Default constructor called
Copy constructor called
Copy assignment operator called
getRawBits member function called
Default constructor called
Copy assignment operator called
getRawBits member function called
getRawBits member function called
0
getRawBits member function called
0
getRawBits member function called
0
Destructor called
Destructor called
Destructor called
$>
소수부를 표현할 비트가 고정되어 있는 방식
2진수 변환 후 정수부에 1만 남을 때까지 소수점을 왼쪽으로 이동시키는 정규화 과정을 거치는 방식
1.xxx... * 2^n
n
)에 bias를 더한 값을 지수부에 저장 (지수의 부호를 표현하기 위해 필요)2^(8 - 1) - 1 = 127
xxx...
)는 가수부(23비트)에 그대로 저장 (정규화 후 1.11101 * 2^2
)면 가수부는 11101
)<cmath>
의 roundf()
인자로 주어진 수를 반올림하여 리턴
float roundf (float x);
Fixed
클래스const int
를 인자로 받는 생성자: 인자로 받은 수를 고정 소수점 값으로 변환const float
를 인자로 받는 생성자: 인자로 받은 수를 고정 소수점 값으로 변환float toFloat( void ) const;
: 고정 소수점 값을 부동 소수점 값으로 변환int toInt( void ) const;
: 고정 소수점 값을 정수로 변환<<
)를 고정 소수점 값의 부동 소수점 표현을 매개 변수로 전달된 출력 스트림에 삽입toFloat()
호출서브젝트의 고정 소수점의 소수부 표현 비트는 8비트
👉 32 비트 체계에서 앞의 24비트를 정수로, 뒤의 8비트를 소수로 표현
<<
연산으로 8비트의 빈 공간을 만듦n << 8
<<
같은 쉬프트 연산자를 사용할 수 없음int
이므로 (남은 소수부를 없애고 + 좀더 정확한 연산을 위해) 허용 함수인 roundf
를 사용하여 반올림roundf(n * (1 << 8))
int
)을 float
으로 변환한 뒤 <<
연산한 값을 다시 되돌림static_cast<float>(n) / (1 << 8)
int main(void) {
Fixed a;
Fixed const b(10);
Fixed const c(42.42f);
Fixed const d(b);
a = Fixed(1234.4321f);
std::cout << "a is " << a << std::endl;
std::cout << "b is " << b << std::endl;
std::cout << "c is " << c << std::endl;
std::cout << "d is " << d << std::endl;
std::cout << "a is " << a.toInt() << " as integer" << std::endl;
std::cout << "b is " << b.toInt() << " as integer" << std::endl;
std::cout << "c is " << c.toInt() << " as integer" << std::endl;
std::cout << "d is " << d.toInt() << " as integer" << std::endl;
return (0);
}
$> ./a.out
Default constructor called
Int constructor called
Float constructor called
Copy constructor called
Copy assignment operator called
Float constructor called
Copy assignment operator called
Destructor called
a is 1234.43
b is 10
c is 42.4219
d is 10
a is 1234 as integer
b is 10 as integer
c is 42 as integer
d is 10 as integer
Destructor called
Destructor called
Destructor called
Destructor called
$>
멤버 함수로 구현
>
<
>=
<=
==
!=
+
-
*
/
전/후위 ++
, 전/후위 --
비교 연산자 오버로딩 활용
min()
: 2개의 고정 소수점 수에 대한 참조를 받아서 작은 것 리턴min()
: 2개의 const 고정 소수점 수에 대한 참조를 받아서 작은 것 리턴max()
: 2개의 고정 소수점 수에 대한 참조를 받아서 큰 것 리턴max()
: 2개의 const 고정 소수점 수에 대한 참조를 받아서 큰 것 리턴int main(void) {
Fixed a;
Fixed const b(Fixed(5.05f) * Fixed(2));
std::cout << a << std::endl;
std::cout << ++a << std::endl;
std::cout << a << std::endl;
std::cout << a++ << std::endl;
std::cout << a << std::endl;
std::cout << b << std::endl;
std::cout << Fixed::max(a, b) << std::endl;
return (0);
}
$> ./a.out
0
0.00390625
0.00390625
0.00390625
0.0078125
10.1016
10.1016
$>
이진 공간 분할법
👉 서브젝트에서는 점이 삼각형 안에 있는지만 판단하면 되기 때문에 굳이 트리까지 생성할 필요는 없을 듯
주어진 점이 삼각형 안에 있는지 아닌지 판단하기
Point
클래스Fixed const x
Fixed const y
x
, y
를 0
으로 초기화const float
을 받아서 x
, y
를 초기화하는 생성자복사 대입 연산자를 오버로딩할 때 const 값을 리턴하지 않아 발생하는 오류
Fixed
클래스에서=
연산자를 오버로딩할 때Fixed &
형을 반환하기 때문에,Point
의 복사 대입 연산자를 오버로딩하면서_x = point.getX();
와 같이 사용할 수 없음
👉const_cast<T>
로const
를 일시적으로 제거
bool bsp( Point const a, Point const b, Point const c, Point const point);
a
, b
, c
: 삼각형의 꼭짓점point
: 확인할 점true
: 점이 삼각형 안에 있는 경우false
: 그렇지 않은 경우 (삼각형의 꼭짓점이나 변에 있는 경우 포함)