CppModule 02

ex00 My First Canonical Class

์˜๋„๊ฐ€ ๋ญ”๋ฐ?????? ์•„๋ž˜์—์„œ ์žฌ๋Œ€๋กœ ๋งŒ๋“ค๊ฑฐ๊ณ , ์—ฌ๊ธฐ๋Š” ๊ทธ๋ƒฅ ์ง„์งœ canonical class form์œผ๋กœ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•ด๋ณด๋Š” ๋ถ€๋ถ„. ์ผ๋‹จ ๋ณ„ ๊ธฐ๋Šฅ ์—†๋”๋ผ๋„ ์—ฌ๊ธฐ์„œ๋Š” ๋งŒ๋“ค๋ผ๊ณ  ํ•˜๋Š” ํผ ๋Œ€๋กœ ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.

Canonical์ด๋ž€?

Canonical :์ •๊ทœ์ ์ธ. -> Canonical form class :์ •๊ทœ์ ์ธ ํ˜•ํƒœ์˜ ํด๋ž˜์Šคโ€ฆ

Orthodox canonical class form = OCCF

์‚ฌ์‹ค OCCF์— ๋Œ€ํ•ด ์˜คํ”ผ์…œํ•œ ๋ ˆํผ๋Ÿฐ์Šค๋Š” ์—†์–ด๋ณด์ธ๋‹คโ€ฆ ํ•˜์ง€๋งŒ ๊ด€๋ก€์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๋‚ด์šฉ์ด ๊ฐ€์žฅ ์ค‘์š”ํ•ด ๋ณธ์ธ๋‹ค.

OCCF๋ฅผ ์ค€์ˆ˜ํ•˜๋Š” ํด๋ž˜์Šค๋Š” c++98, c++03์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ž๋™์ ์œผ๋กœ ์ƒ์„ฑํ•˜๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ํ•ญ๋ชฉ๋“ค์— ๋Œ€ํ•ด์„œ ์„ ์–ธ ๋ฐ ์ •์˜ํ•œ๋‹ค(=์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ž๋™ ์ƒ์„ฑ๋˜๋Š” ํ•ญ๋ชฉ๋“ค์— ๋Œ€ํ•ด์„œ ํ•ธ๋“ค๋ง ํ•ด๋†“๋Š”๋‹ค).

  1. ๊ธฐ๋ณธ์ƒ์„ฑ์ž -> Class::Class()
  2. ๋ณต์‚ฌ ์ƒ์„ฑ์ž(๋Œ€์ž… ์ƒ์„ฑ์ž?) -> Class::Class(const Class&)
  3. ๋Œ€์ž… ์—ฐ์‚ฐ์ž -> Class& operator=(const Class&)
  4. ์†Œ๋ฉธ์ž -> Class::~Class()

ref : advanced c++ programming styles and idioms, James O. Coplien ๋ฐœ์ทŒ ๊ธ€, Orthodox canonical class form

ex01 Towards a more useful fixed point class

ex00์—์„œ ๋งŒ๋“  ํด๋ž˜์Šค์— ๋ณธ๊ฒฉ์ ์œผ๋กœ ์“ธ๋งŒํ•œ ๊ธฐ๋Šฅ๋“ค์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋‹จ๊ณ„

๊ณ ์ •์†Œ์ˆ˜์ 

๊ณผ์ œ์—์„œ ์š”๊ตฌํ•˜๋Š” ๊ณ ์ • ์†Œ์ˆ˜์ ์˜ ํ˜•ํƒœ๋Š” 32bit(float)์ค‘ 24bit๋Š” ์ •์ˆ˜๋ฐ์ดํ„ฐ, 8bit๋Š” ์†Œ์ˆ˜๋ฐ์ดํ„ฐ์ด๋‹ค. ์ฆ‰, ์†Œ์ˆ˜๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ํฌ๊ธฐ๊ฐ€ 8bit๋กœ ๊ณ ์ •์ ์ธ ์ž๋ฃŒํ˜•์„ ์š”๊ตฌํ•œ๋‹ค.

float๋ฐ์ดํ„ฐ๋ฅผ 8bit๋งŒํผ shift(= *256)ํ•˜์—ฌ ์†Œ์ˆ˜๋ถ€๋ถ„ 8bit๋ฅผ intํ˜•์œผ๋กœ ๋ณด์กดํ•˜๋‹ค ํ•„์š”ํ• ๋•Œ floatํ˜•์œผ๋กœ ๋ณต๊ตฌํ•˜๊ณ ์ž ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“œ๋Š”๊ฒŒ ๊ฐ€์žฅ ์ดํ•ด๊ฐ€ ๋น ๋ฅด๋‹ค.

float floatFloat = 42.4199982;
float floatTemp;
int   intTemp;

// 8bit๊ธธ์ด์˜ ์†Œ์ˆ˜๋ถ€๋งŒ ๋ณด์กดํ•˜์—ฌ intํ˜•์œผ๋กœ ์ €์žฅ.
floatTemp = floatFloat * (1 << 8);
intTemp = (int)roundf(floatTemp);

// int๋กœ ์ €์žฅ๋œ๊ฑธ ๋ณต๊ตฌํ•˜์—ฌ ์‚ฌ์šฉ.
std::cout << ((float)intTemp / (1 << 8)) << std::endl;

์œ„์˜ ์ฝ”๋“œ๋ฅผ ์„ค๋ช…ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

๋ฐ‘์ค„ : ๋ณด์กดํ•˜๊ณ ์ž ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋‚˜ํƒ€๋ƒ„.

์ด๋•Œ ๋“ค์–ด์™€์„œ ๋ณ€ํ™˜ํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ int์ธ์ง€ float์ธ์ง€๋Š” ์•Œ ์ˆ˜ ์—†์œผ๋ฏ€๋กœ intํ˜•์„ ์ž…๋ ฅ๋ฐ›์„๋•Œ๋„ left shift์—ฐ์‚ฐ์„ ํ•˜๊ณ , ์ถœ๋ ฅํ• ๋•Œ ์ผ๊ด„์ ์œผ๋กœ right shift์—ฐ์‚ฐ์„ ํ•˜์—ฌ ๋ณด์กดํ•˜๊ธฐ ์œ„ํ•ด ์™ผ์ชฝ์œผ๋กœ ์ด๋™์‹œ์ผฐ๋˜ ์†Œ์ˆ˜์  8bit๋ฅผ ๋‹ค์‹œ ์˜ค๋ฅธ์ชฝ์œผ๋กœ 8bit์˜ฎ๊ธด๋‹ค.

์†”์ฐํžˆโ€ฆ ๋ณธ๋ฌธ์—์„œ ์–ด๋–ค๊ฑธ ์š”๊ตฌํ•˜๋Š”์ง€ ํŒŒ์•…ํ•˜๊ธฐ๋„ ํž˜๋“ ๋ฐ, ์ด๊ฑธ ์ƒ๊ฐํ•ด๋‚ด๊ธฐ๋Š” ์ •๋ง ํž˜๋“ค๊ฑฐ ๊ฐ™๋‹ค. ์ด ๋ธ”๋กœ๊ทธ์—์„œ ๊ณ ์ •์†Œ์ˆ˜์ ์„ ์–ด๋–ป๊ฒŒ ๋งŒ๋“ค์ง€ ๊ฐœ๋…์„ ํŒŒ์•…ํ•˜๊ณ , IEEE 754 Converter์—์„œ bit๊ฐ’์ด ์–ด๋–ป๊ฒŒ ๋ณ€ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋ฉด์„œ ์™„๋ฒฝํ•˜๊ฒŒ ์ดํ•ดํ•˜๋ ค๊ณ  ๋…ธ๋ ฅํ–ˆ๋‹ค.

์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ๋”ฉ(ex01, ex02)

์˜ˆ์ œ๋ฅผ ์“ฑ ๋ณด๋‹ˆ ex02์— ์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ๋”ฉ์„ ์ง‘์ค‘์ ์œผ๋กœ ํ•˜๊ฒŒ ๋˜๋ฏ€๋กœ, ํ•œ๋ฒˆ์— ์ •๋ฆฌ. ๊ณผ์ œ์—์„œ ์š”๊ตฌ : ๋Œ€์ž… ์—ฐ์‚ฐ์ž(=), ์‚ฐ์ˆ ์—ฐ์‚ฐ์ž(+, -, *, /), ๋น„๊ต์—ฐ์‚ฐ์ž(>, <, >=, <=, ==, !=), ์ฆ๊ฐ ์—ฐ์‚ฐ์ž(++Fix, --Fix, Fix++, Fix--), stream ์‚ฝ์ž… ์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ๋”ฉ(<<)

์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ๋”ฉ ์„ ์–ธ ์œ„์น˜

์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ๋”ฉ์€ ํด๋ž˜์Šค ๋‚ด์—์„œ ํ•˜๊ฑฐ๋‚˜, ํด๋ž˜์Šค ๋ฐ–์—์„œ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋•Œ ์ž๊ธฐ ์ž์‹ ์„ ๋ฆฌํ„ดํ•˜๊ฑฐ๋‚˜ private์˜์—ญ์˜ ๋ฉค๋ฒ„๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ์—ฐ์‚ฐ์ž๋“ค์€ ๋‚ด๋ถ€ ์—ฐ์‚ฐ์ž๋กœ ์˜ค๋ฒ„๋กœ๋”ฉ ํ•œ๋‹ค. overloading table

์ญ‰ ์ฐพ์•„๋ณธ ๊ฒฐ๊ณผ ํŠน์ • ๋ช‡๊ฐœ๋ฅผ ์ œ์™ธํ•˜๊ณ ๋Š” ์–ด๋””์„œ ๋ฉค๋ฒ„๋กœ ์„ ์–ธ ํ• ์ง€ ๋ง์ง€๋Š” ํฌ๊ฒŒ ์ƒ๊ด€ ์—†๋Š”๊ฒƒ ๊ฐ™๋‹ค. ํ•˜์ง€๋งŒ ๊ฐ์ฒด์ง€ํ–ฅ์ ์ธ ๊ด€์ ์—์„œ ๋ณผ๋•Œ ์ „์—ญ์€ ์ง€์–‘ํ•˜๋Š”๊ฒŒ ์ข‹๋‹ค. ๋”ฐ๋ผ์„œ ํ•ด๋‹น ๊ณผ์ œ์—์„œ๋Š” ํฐ ์ด์œ ๊ฐ€ ์—†์œผ๋ฉด ๋ฉค๋ฒ„๋กœ์„œ ์˜ค๋ฒ„๋กœ๋”ฉํ•œ๋‹ค.

์˜ค๋ฒ„๋กœ๋”ฉ ์ œํ•œ์‚ฌํ•ญ

๋Œ€์ž… ์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ(=, ์ปดํŒŒ์ผ๋Ÿฌ ์ž๋™ ์ƒ์„ฑ)

Fix& operator=(Fix& other);

-> ์–‹์€๋ณต์‚ฌ ๊นŠ์€๋ณต์‚ฌ์— ์ฃผ์˜.

๋ณต์‚ฌ ์ƒ์„ฑ์ž(Fix(Fix& other))์— ํ™œ์šฉ ๊ฐ€๋Šฅํ•˜๋ฉฐ, ๋ณต์‚ฌ์ƒ์„ฑ์ž ๋˜ํ•œ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์—†์œผ๋ฉด ์ž๋™์ƒ์„ฑํ•œ๋‹ค.

์‚ฐ์ˆ  ์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ๋”ฉ(+, -, *, /)

Fix operator+(Fix& term);  // a + b โ†’ a.operator+(b)
Fix operator-(Fix& term);  // a - b โ†’ a.operator-(b)
Fix operator*(Fix& term);  // a * b โ†’ a.operator*(b)
Fix operator/(Fix& term);  // a / b โ†’ a.operator/(b)

๋น„๊ต์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ๋”ฉ(>, <, >=, <=, ==, !=)

bool operator>(Fix& term);  // a > b  โ†’ a.operator>(b)
bool operator<(Fix& term);  // a < b  โ†’ a.operator<(b)
bool operator>=(Fix& term); // a >= b โ†’ a.operator>=(b)
bool operator<=(Fix& term); // a <= b โ†’ a.operator<=(b)
bool operator==(Fix& term); // a == b โ†’ a.operator==(b)
bool operator!=(Fix& term); // a != b โ†’ a.operator!=(b)

์ฆ๊ฐ์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ๋”ฉ(++Fix, --Fix, Fix++, Fix--)

์ฆ๊ฐ์—ฐ์‚ฐ์ž๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜ int ์—ฌ๋ถ€์— ๋”ฐ๋ผ ์ „์œ„์ฆ๊ฐ๊ณผ ํ›„์œ„์ฆ๊ฐ์„ ๊ตฌ๋ถ„ํ•œ๋‹ค. ์žˆ์œผ๋ฉด ํ›„์œ„์ด๋ฉฐ ๋‹จ์ง€ ๋‹จ์ˆ˜์œ„ ์ „์œ„์™€ ํ›„์œ„๋ฅผ ๊ตฌ๋ถ„ํ•˜๋Š” ์šฉ๋„์ด๋‹ค.

๋˜ํ•œ ์ „์œ„์˜ ๊ฒฝ์šฐ ์ฆ๊ฐ์ด ๋ฐ˜์˜๋œ ํ˜„์žฌ์˜ ์ž์‹ (Fix&)์„ ๋ฆฌํ„ดํ•˜๊ณ , ํ›„์œ„๋Š” ๋ฐ˜์˜๋˜๊ธฐ ์ด์ „์˜ ๊ฐ์ฒด(Fix)๋ฅผ ๋ฏธ๋ฆฌ ๋ณต์‚ฌํ•˜๊ณ  ๋ฆฌํ„ดํ•œ๋‹ค.

Fix& operator++();      // ++fix
Fix& operator--();      // --fix
Fix operator++(int);    // fix++
Fix operator--(int);    // fix--

์ถ”๊ฐ€ : ๋ณดํ†ต์˜ ํ›„์œ„ ์ฆ๊ฐ์—ฐ์‚ฐ์˜ ๊ฒฝ์šฐ ํ›„์œ„์—ฐ์‚ฐ๋ณด๋‹ค ๋Š๋ฆฌ๋‹ค. ์ฆ๊ฐ ์ด์ „์˜ ๊ฐ์ฒด๋ฅผ ๋ฏธ๋ฆฌ ๋ณต์‚ฌํ•ด์•ผํ•˜๊ณ  ์ด๋ฅผ ํฌ์ธํ„ฐ/์ฐธ๊ณ ๊ฐ€ ์•„๋‹ˆ๋ผ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

stream ์‚ฝ์ž…/์ถ”์ถœ ์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ๋”ฉ(<<, >>)

  1. ํ•ด๋‹น ์—ฐ์‚ฐ์ž๋“ค์€ ์˜ค๋ฅธ์ชฝ ์ธ์ž๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ์ •์˜ํ•œ ํƒ€์ž…์„ ๋ฐ›์œผ๋ฏ€๋กœ, ์ „์—ญ์œผ๋กœ ์„ ์–ธํ•œ๋‹ค.
  2. std::cout << fix๊ฐ€ ๋ฉค๋ฒ„ํ•จ์ˆ˜๋กœ ์„ ์–ธ๋œ๋‹ค๋ฉด, std::cout.operator<<(fix)๋กœ std::cout์ด operator<<๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ํด๋ž˜์Šค๊ฐ€ ๋  ๊ฒƒ์ด๋‹ค. ํ•˜์ง€๋งŒ iostream ๋ฐ ๊ธฐํƒ€ ์ŠคํŠธ๋ฆผ๋“ค์€ C++ ํ‘œ์ค€ ํด๋ž˜์Šค์ด๋ฏ€๋กœ ๋งด๋ฒ„๋กœ ์˜ค๋ฒ„๋ผ์ด๋”ฉ์ด ๋ถˆ๊ฐ€ํ•˜๋‹ค. ๋”ฐ๋ผ์„œ operator<<(std::cout, fix)ํ˜•ํƒœ๋กœ ์ •์˜ํ•˜๊ธฐ ์œ„ํ•ด ์ „์—ญ์œผ๋กœ ์„ ์–ธํ•œ๋‹ค.
    ostream& operator<<(std::ostream& os, Fix& term);	//std::out << fix โ†’ operator(std::out, fix)
    

ref : cppreference.com, ansohxxn ๋ธ”๋กœ๊ทธ

Fixed operator*(Fixed& other) vs Fixed operator*(const Fixed& other)

const์—†์œผ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—๋Ÿฌ ๋ฐœ์ƒ.

main.cpp:6:33: error: invalid operands to binary expression ('Fixed' and 'Fixed')
  Fixed const b( Fixed( 5.05f ) * Fixed( 2 ) );
                 ~~~~~~~~~~~~~~ ^ ~~~~~~~~~~
./Fixed.hpp:35:8: note: candidate function not viable: expects an l-value for 1st argument
        Fixed operator*(Fixed& other);
              ^
1 error generated.

์œ„์˜ ์—๋Ÿฌ๋‚ด์šฉ์—์„œ Fixed( 5.05f )์™€ Fixed( 2 )๋Š” ๊ฐ๊ฐ ์ž„์‹œ๊ฐ์ฒด(l-value)๊ฐ€ ์ƒ์„ฑํ•œ๋‹ค. ์ด๋•Œ C++์—์„œ non-const๋ฉค๋ฒ„๋Š” ์ž„์‹œ๊ฐ์ฒด๊ฐ™์€ l-value์— ๋ฐ”์ธ๋”ฉ(์ฐธ์กฐ)ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์œ„์™€ ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. -> lvaue๋Š” ์ˆ˜์ • ๋ถˆ๊ฐ€๋Šฅํ•œ ์ž„์‹œ์ ์ธ ๊ฐ’๋“ค์ธ๋ฐ, const๊ฐ€ ์•„๋‹Œ ์ฐธ์กฐ๋ฅผ ํ•˜๊ฒŒ ๋˜๋ฉด ์ˆ˜์ •์„ ํ•˜๊ฒŒ ๋˜๋ฏ€๋กœโ€ฆ

ref : stack overflow, reference binding