Computer-Science

Operator Overloading

Contents

  1. Introduction
  2. Operator Overloading ๊ธฐ๋ณธ์‚ฌํ•ญ
  3. Operator Overloading ์ œํ•œ์กฐ๊ฑด
  4. Operator Functions as Class Members vs. Global Functions
  5. Overloading Stream Insertion and Stream Extraction Operators
  6. Overloading Unary Operators
  7. Overloading Binary Operators
  8. Case Study: Array Class
  9. Overloading ++ and โ€“
  10. Case Study: A Date Class

1. Introduction

์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ๋”ฉ์ด๋ž€?

2. Operator Overloading ๊ธฐ๋ณธ์‚ฌํ•ญ

์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ๋”ฉ ๋ฐฉ๋ฒ•

Operator+ ๋ผ๋Š” ์ด๋ฆ„์˜ ํ•จ์ˆ˜

class Point
{
private:
    int x, y;

public:
    Point(int x_, int y_)
    {
        x = x_;
        y = y_;
    }
    void print()
    {
        cout << "x : " << x << ", y : " << y << "\n";
    }
    Point operator+(Point &p)
    {
        x = x + p.x;
        y = y + p.y;
        return Point(x, y);
    }
};
int main(void)
{
    Point p1 = {1, 1};
    Point p2(2, 2);
    Point p3 = p1 + p2;
    p3.print();
    return 0;
}

Good Programming Practice

Overloaded operators should mimic the functionality of their built-in counterpartsโ€”for example, the + operator should be overloaded to perform addition, not subtraction. Avoid excessive or inconsistent use of operator overloading, as this can make a program cryptic and difficult to read.

์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ๋”ฉ ๋ฐฉ๋ฒ•

์˜ค๋ฒ„๋กœ๋”ฉ์€ ๊ฐ์ฒด๊ฐ„ ์—ฐ์‚ฐ์˜ ๊ฐ„๊ฒฐํ•œ ํ‘œํ˜„์„ ์ œ๊ณต

3. Operator Overloading ์ œํ•œ์กฐ๊ฑด

์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ๋”ฉ์œผ๋กœ๋„ ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒƒ์€?

์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ๋”ฉํ•  ์ˆ˜ ์—†๋Š” ์—ฐ์‚ฐ์ž

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2021-12-02 แ„‹แ…ฉแ„’แ…ฎ 9 18 08

4. Operator Functions as Class Members vs. Global Functions

๋ฉค๋ฒ„ ํ•จ์ˆ˜๋กœ์„œ์˜ ์—ฐ์‚ฐ์ž ํ•จ์ˆ˜

์ „์—ญ ํ•จ์ˆ˜๋กœ์„œ์˜ ์—ฐ์‚ฐ์ž ํ•จ์ˆ˜

์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ๋”ฉ๊ณผ ์—ฐ์‚ฐ์˜ ๊ตํ™˜ ๋ฒ•์น™

5. Overloading Stream Insertion and Stream Extraction Operators

์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ๋”ฉ๊ณผ stream ์—ฐ์‚ฐ์ž

์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ๋”ฉ๊ณผ stream ์—ฐ์‚ฐ์ž ์˜ˆ์ œ

PhoneNumber.h

#pragma once

#include <iostream>
using namespace std;

class PhoneNumber
{
    friend ostream &operator<<(ostream &, const PhoneNumber &);
    friend istream &operator>>(istream &, PhoneNumber &);

private:
    string areaCode;
    string exchange;
    string line;
};

PhoneNumber.cpp

// #include <iostream>

#include <iomanip>
#include "PhoneNumber.h"

using namespace std;

ostream &operator<<(ostream &output, const PhoneNumber &number)
{
    output << "(" << number.areaCode << ") "
           << number.exchange << "-" << number.line;

    return output;
}

istream &operator>>(istream &input, PhoneNumber &number)
{
    input.ignore();
    input >> setw(3) >> number.areaCode;
    input.ignore(2);
    input >> setw(3) >> number.exchange;
    input.ignore();
    input >> setw(4) >> number.line;

    return input;
}

istream &operator>>(istream &input, PhoneNumber &number)
{
    input.ignore();
    input >> setw(3) >> number.areaCode;
    input.ignore(2);
    input >> setw(3) >> number.exchange;
    input.ignore();
    input >> setw(4) >> number.line;

    return input;
}

driver

#include <iostream>
using namespace std;

#include "PhoneNumber.h"

int main()
{
    PhoneNumber phone;

    cout << "Enter phone number in the forms (123) 456-7890:" << endl;

    cin >> phone;

    cout << "The phone number entered was: ";

    cout << phone << endl;
    return 0;
}

6. Overloading Unary Operators

๋‹จํ•ญ ์—ฐ์‚ฐ์ž (unary operator) ์˜ค๋ฒ„๋กœ๋”ฉ

์ฆ๊ฐ€, ๊ฐ์†Œ ์—ฐ์‚ฐ์ž์˜ ์˜ค๋ฒ„๋กœ๋”ฉ

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2021-12-02 แ„‹แ…ฉแ„’แ…ฎ 9 31 41

7. Overloading Binary Operators

์ดํ•ญ ์—ฐ์‚ฐ์ž (binary operator) ์˜ค๋ฒ„๋กœ๋”ฉ

์˜ˆ์ œ: += ์˜ค๋ฒ„๋กœ๋”ฉ

Non-static ๋ฉค๋ฒ„ ํ•จ์ˆ˜๋ผ๋ฉด, ํ•˜๋‚˜์˜ ์ธ์ˆ˜๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

class String
{
public:
  const String & operator+=( const String & );
  โ€ฆ
};

์ „์—ญ ํ•จ์ˆ˜๋ผ๋ฉด, ๋‘ ๊ฐœ์˜ ์ธ์ˆ˜๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

8. Case Study: Array Class

C++ ๋ฐฐ์—ด์˜ ๋‹จ์ 

C++ ๋ฐฐ์—ด์˜ ๊ฐœ์„ 

Array ํด๋ž˜์Šค์˜ ๋ณต์‚ฌ ์ƒ์„ฑ์ž(Copy Constructor)

์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ๋”ฉ์œผ๋กœ ๊ฐœ์„ ๋œ Array ํด๋ž˜์Šค ์˜ˆ์ œ

Array.h

#ifndef ARRAY_H
#define ARRAY_H

#include <iostream>
using std::istream;
using std::ostream;

class Array
{
    friend ostream &operator<<(ostream &, const Array &);
    friend istream &operator>>(istream &, Array &);

public:
    Array(int = 10);
    Array(const Array &);
    ~Array();
    int getSize() const;

    const Array &operator=(const Array &);
    bool operator==(const Array &) const;

    bool operator!=(const Array &right) const
    {
        return !(*this == right);
    }

    int &operator[](int);

    int operator[](int) const;

private:
    int size;
    int *ptr;
};

#endif

Array.cpp

#include <iostream>
using std::cerr;
using std::cin;
using std::cout;
using std::endl;

#include <iomanip>
using std::setw;

#include <cstdlib>;
using std::exit;

#include "Array.h"

Array::Array(int arraySize)
{
    size = (arraySize > 0 ? arraySize : 10);
    ptr = new int[size];

    for (int i = 0; i < size; i++)
    {
        ptr[i] = 0;
    }
}

Array::Array(const Array &arrayToCopy)
    : size(arrayToCopy.size)
{
    ptr = new int[size];

    for (int i = 0; i < size; i++)
    {
        ptr[i] = arrayToCopy.ptr[i];
    }
}

Array::~Array()
{
    delete[] ptr;
}

int Array::getSize() const
{
    return size;
}

const Array &Array::operator=(const Array &right)
{
    if (&right != this)
    {
        if (size != right.size)
        {
            delete[] ptr;
            size = right.size;
            ptr = new int[size];
        }

        for (int i = 0; i < size; i++)
        {
            ptr[i] = right.ptr[i];
        }
    }

    return *this;
}

bool Array::operator==(const Array &right) const
{
    if (size != right.size)
    {
        return false;
    }

    for (int i = 0; i < size; i++)
    {
        if (ptr[i] != right.ptr[i])
        {
            return false;
        }
    }

    return true;
}

int &Array::operator[](int subscript)
{
    if (subscript < 0 || subscript >= size)
    {
        cerr << "\nError: Subscript " << subscript
             << "out of range" << endl;
        exit(1);
    }

    return ptr[subscript];
}

int Array::operator[](int subscript) const
{
    if (subscript < 0 || subscript >= size)
    {
        cerr << "\nError: Subscript " << subscript
             << " out of range" << endl;
        exit(1);
    }

    return ptr[subscript];
}

istream &operator>>(istream &input, Array &a)
{
    for (int i = 0; i < a.size; i++)
    {
        input >> a.ptr[i];
    }

    return input;
}

ostream &operator<<(ostream &output, const Array &a)
{
    int i;

    for (i = 0; i < a.size; i++)
    {
        output << setw(12) << a.ptr[i];

        if ((i + 1) % 4 == 0)
        {
            output << endl;
        }
    }

    if (i % 4 != 0)
    {
        output << endl;
    }

    return output;
}

main.cpp

#include <iostream>
using std::cin;
using std::cout;
using std::endl;

#include "Array.h"

int main()
{
    Array integers1(7);
    Array integers2;

    cout << "Size of Array integers1 is "
         << integers1.getSize()
         << "\nArray after initialization:\n"
         << integers1;

    cout << "Size of Array integers2 is "
         << integers2.getSize()
         << "\nArray after initialization:\n"
         << integers2;

    cout << "\nEnter 17 integers:" << endl;
    cin >> integers1 >> integers2;

    cout << "\nAfter input, the Arrays contatin:\n"
         << "integers1:\n"
         << integers1
         << "integers2:\n"
         << integers2;

    cout << "\nEvaluating: integers1 != integers2" << endl;

    if (integers1 != integers2)
    {
        cout << "integers1 and integers2 are not equal" << endl;
    }

    Array integers3(integers1);

    cout << "\nSize of Array integers3 is "
         << integers3.getSize()
         << "\nArray after initialization:\n"
         << integers3;

    cout << "\nAssigning integers2 to integers1:" << endl;
    integers1 = integers2;

    cout << "integers1:\n"
         << integers1
         << "integers2:\n"
         << integers2;

    cout << "\nEvaluating: integers1 == integers2" << endl;

    return 0;
}

9. Overloading ++ and โ€“

์ฆ๊ฐ€/๊ฐ์†Œ ์—ฐ์‚ฐ์ž์˜ ์˜ค๋ฒ„๋กœ๋”ฉ

์ ‘๋‘(prefix), ์ ‘๋ฏธ(postfix) ์ฆ๊ฐ€์˜ ๊ตฌ๋ถ„

์ ‘๋‘(prefix), ์ ‘๋ฏธ(postfix) ์ฆ๊ฐ€์˜ ๋ฐ˜ํ™˜๊ฐ’

10. Case Study: A Date Class

Date ํด๋ž˜์Šค ์˜ˆ์ œ

๊ฐœ์š”

date.h

#pragma once

#include <iostream>
using std::ostream;

class Date
{
    friend ostream &operator<<(ostream &, const Date &);

public:
    Date(int m = 1, int d = 1, int y = 1900);
    void setDate(int, int, int);
    Date &operator++();
    Date operator++(int);
    const Date &operator+=(int);
    bool leapYear(int) const;
    bool endOfMonth(int) const;

private:
    int month;
    int day;
    int year;

    static const int days[];
    void helpIncrement();
};

date.cpp

#include <iostream>
#include "Date.h"

const int Date::days[] =
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

Date::Date(int m, int d, int y)
{
    setDate(m, d, y);
}

void Date::setDate(int mm, int dd, int yy)
{
    month = (mm >= 1 && mm <= 12) ? mm : 1;
    year = (yy >= 1900 && yy <= 2100) ? yy : 1900;

    if (month == 2 && leapYear(year))
        day = (dd >= 1 && dd <= 29) ? dd : 1;
    else
        day = (dd >= 1 && dd <= days[month]) ? dd : 1;
}

Date &Date::operator++()
{
    helpIncrement();
    return *this;
}

Date Date::operator++(int)
{
    Date temp = *this;
    helpIncrement();

    return temp;
}

const Date &Date::operator+=(int additionalDays)
{
    for (int i = 0; i < additionalDays; i++)
    {
        helpIncrement();
    }
    return *this;
}

bool Date::leapYear(int testYear) const
{
    if (testYear % 400 == 0 ||
        (testYear % 100 != 0 && testYear % 4 == 0))
        return true;
    else
        return false;
}

bool Date::endOfMonth(int testDay) const
{
    if (month == 2 && leapYear(year))
        return testDay == 29;
    else
        return testDay == days[month];
}

void Date::helpIncrement()
{
    if (!endOfMonth(day))
        day++;
    else
    {
        if (month < 12)
        {
            month++;
            day = 1;
        }
        else
        {
            year++;
            month = 1;
            day = 1;
        }
    }
}

ostream &operator<<(ostream &output, const Date &d)
{
    static char *monthName[13] = {"", "January", "Feburary", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
    output << monthName[d.month] << ' ' << d.day << ", " << d.year;
    return output;
}

main.cpp

#include <iostream>
using std::cout;
using std::endl;

#include "Date.h"

int main()
{
    Date d1;
    Date d2(12, 27, 1992);
    Date d3(0, 99, 8045);

    cout << "d1 is " << d1 << "\nd2 is " << d2 << "\nd3 is " << d3;
    cout << "\n\nd2 += 7 is " << (d2 += 7);

    d3.setDate(2, 28, 1992);
    cout << "\n\n d3 is " << d3;
    cout << "\n++d3 is " << ++d3 << " (leap year allows 29th)";

    Date d4(7, 13, 2002);

    cout << "\n\nTesting the prefix increment operator:\n"
         << " d4 is " << d4 << endl;
    cout << "++d4 is " << ++d4 << endl;
    cout << " d4 is " << d4;
    cout << "\n\nTesting the postfix increment operator:\n"
         << " d4 is " << d4 << endl;
    cout << "d4++ is " << d4++ << endl;
    cout << " d4 is " << d4 << endl;

    return 0;
}