Updated:

3 minute read

함수 오버로딩

  • 이름은 같지만 매개변수의 타입 혹은 개수가 다른 함수
  • 반환형이 다른 것은 인정되지 않음
  • 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