[C++] 오버로딩/오버라이딩
Updated:
함수 오버로딩
- 이름은 같지만 매개변수의 타입 혹은 개수가 다른 함수
- 반환형이 다른 것은 인정되지 않음
- bool과 string으로만 오버로딩 할 경우 char형 배열/포인터는 string이 아닌 bool형으로 판단
- 코드
#include <iostream> #include <string> using namespace std; void func(const int& i) { cout << "func(const int& i)" << endl; } void func(const bool& bArg) { cout << "func(const bool &bArg)" << endl; } void func(const string& s) { cout << "func(const string& s)" << endl; } int main() { func(1); func(true); func("abc"); func(string("abc")); return 0; }
- 실행 결과
func(const int& i) func(const bool &bArg) func(const bool &bArg) func(const string& s)
연산자 오버로딩
- 디폴트 대입 연산자
- 디폴트 복사 생성자와 마찬가지로 얕은 복사를 하므로 주의
- +, -, *, /의 경우 a = b + c + b 등의 식을 계산할때 상식적인 의미 전달을 위해 일반적으로는 반환형을 레퍼런스로 선언하지 않음
- 자기 자신을 리턴하지 않는 연산자(+, -, *, /)는 외부 함수로 선언하는 것이 원칙
- 코드
#include <iostream> #include <string> using namespace std; class Test { private: int i = 0; public: Test(const int& i) : i(i){}; Test(const Test& t) : i(t.i) {} ~Test() = default; Test& operator+=(const Test& t) { (*this) = (*this) + t; return *this; } Test& operator-=(const Test& t) { (*this) = (*this) - t; return *this; } Test& operator*=(const Test& t) { (*this) = (*this) * t; return *this; } Test& operator/=(const Test& t) { (*this) = (*this) / t; return *this; } Test& operator=(const Test& t) { this->i = t.i; return *this; } Test& operator++() { *this += 1; return *this; } Test operator++(int) { Test t(*this); *this += 1; return t; } Test& operator--() { *this -= 1; return *this; } Test operator--(int) { Test t(*this); *this -= 1; return t; } bool operator==(const Test& t) const { return this->i == t.i; } friend Test operator+(const Test& t1, const Test& t2); friend Test operator-(const Test& t1, const Test& t2); friend Test operator*(const Test& t1, const Test& t2); friend Test operator/(const Test& t1, const Test& t2); friend ostream& operator<<(ostream& os, const Test& t); }; Test operator+(const Test& t1, const Test& t2) { return Test(t1.i + t2.i); } Test operator-(const Test& t1, const Test& t2) { return Test(t1.i - t2.i); } Test operator*(const Test& t1, const Test& t2) { return Test(t1.i * t2.i); } Test operator/(const Test& t1, const Test& t2) { return Test(t1.i / t2.i); } ostream& operator<<(ostream& os, const Test& t) { os << t.i; return os; } class Test2 { private: string s = ""; public: Test2(const string& s) : s(s) {} char& operator[](const int index) { return this->s.at(index); } }; class Integer { private: int i = 0; public: Integer(const int& i) : i(i){}; Integer(const Integer& t) : i(t.i) {} ~Integer() = default; operator int() { return this->i; } }; int main() { Test t1(1); Test t2(2); Test t3(3); cout << t1 + t2 << endl; cout << t1 - t2 << endl; cout << t1 * t2 << endl; cout << t1 / t2 << endl; cout << (t1 += t2) << endl; cout << (t1 -= t2) << endl; cout << (t1 *= t2) << endl; cout << (t1 /= t2) << endl; cout << (t1 = t2) << endl; cout << (t1 == t2) << endl; cout << (t1 == t3) << endl; cout << t3++ << endl; cout << ++t3 << endl; cout << t3-- << endl; cout << --t3 << endl; Test2 t4("abc"); cout << t4[1] << endl; Integer i = 1; int ii = i + 2; cout << i << ", " << ii << endl; return 0; }
- 실행 결과
3 -1 2 0 3 1 2 1 2 1 0 3 5 5 3 b 1, 3
함수 오버라이딩
- 기반 클래스의 함수를 파생 클래스가 재정의
- 오버라이드가 안되는 실수를 맞기 위해 오버라이딩된 함수에 override 키워드를 통해 명시적으로 선언해주는 것을 권장
- 코드
#include <iostream> using namespace std; using namespace std; class Base { public: virtual void func() { cout << "Base()::func" << endl; } }; class Derived : public Base { public: virtual void func() override { cout << "Derived()::func" << endl; } }; int main(void) { Base b1; b1.func(); cout << "------" << endl; Derived d; d.func(); cout << "------" << endl; Base& b2 = d; b2.func(); return 0; }
- 실행 결과
Base()::func ------ Derived()::func ------ Derived()::func