سلام!

برای این که خستگی مبحث سربارگذاری عمل گر ها (که آن را در شش جلسه به پایان رساندیم) از تن تان بیرون برود، یک مبحث بسیار ساده ولی مهم را آموزش می دهیم.

فرض کنید که چند class را پیاده سازی کرده اید و حالا می خواهید از همه ی آن ها در برنامه ی خود استفاده کنید. اگر کد همه ی آن ها را در برنامه ی اصلی خود copy کنید، برنامه تان خیلی شلوغ می شود؛ برای همین بهتر است class ها را در فایل های جداگانه پیاده سازی کنید و سپس از آن فایل ها در برنامه ی خود استفاده کنید.

کد زیر را که مربوط به کلاس Point است در نظر بگیرید.

#include <iostream>
#include <cstdio>

using namespace std;

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

    private:

        double _x, _y;
        
    public:

        Point(double = 0, double = 0);

        double x() const;
        double y() const;

        void setX(double);
        void setY(double);

        void print();
        void setCor(double, double);

        Point operator+(const Point&);
        Point operator-(const Point&);
        Point operator*(const Point&);
        Point operator/(const Point&);

        Point operator+(const double&);
        Point operator-(const double&);
        Point operator/(const double&);
        Point operator*(const double&);
        friend Point operator+(const double&, const Point&);
        friend Point operator-(const double&, const Point&);
        friend Point operator*(const double&, const Point&);
        friend Point operator/(const double&, const Point&);

        bool operator==(const Point&);
        bool operator!=(const Point&);
        bool operator>(const Point&);
        bool operator<(const Point&);
        bool operator>=(const Point&);
        bool operator<=(const Point&);

        void operator+=(const Point&);
        void operator-=(const Point&);
        void operator*=(const Point&);
        void operator/=(const Point&);
        void operator+=(const double&);
        void operator-=(const double&);
        void operator*=(const double&);
        void operator/=(const double&);

        Point operator++();
        Point operator++(int);

        Point operator>>(const Point&);
        Point operator<<(const Point&);
        Point operator~();
        Point operator&(const Point&);
        Point operator|(const Point&);
        Point operator^(const Point&);

        void operator>>=(const Point&);
        void operator<<=(const Point&);
        void operator&=(const Point&);
        void operator|=(const Point&);
        void operator^=(const Point&);

        void operator()(const int&, const int&);
        double operator[](const int&);

};

Point::Point(double x, double y){
    this->setX(x);
    this->setY(y);
}

void Point::setX(double x){
    this->_x = x;
}

void Point::setY(double y){
    this->_y = y;
}

double Point::x() const{
    return this->_x;
}

double Point::y() const{
    return this->_y;
}

void Point::print(){
    printf("(%g, %g)", this->x(), this->y());
}

void Point::setCor(double x, double y){
    this->_x = x;
    this->_y = y;
}

Point Point::operator+(const Point &p2){
    return Point(this->x() + p2.x(), this->y() + p2.y());
}

Point Point::operator-(const Point &p2){
    return Point(this->x() - p2.x(), this->y() - p2.y());
}

Point Point::operator*(const Point &p2){
    return Point(this->x() * p2.x(), this->y() * p2.y());
}

Point Point::operator/(const Point &p2){
    return Point(this->x() / p2.x(), this->y() / p2.y());
}

Point Point::operator+(const double &a){
    return Point(this->x() + a, this->y() + a);
}

Point Point::operator-(const double &a){
    return Point(this->x() - a, this->y() - a);
}

Point Point::operator*(const double &a){
    return Point(this->x() * a, this->y() * a);
}

Point Point::operator/(const double &a){
    return Point(this->x() / a, this->y() / a);
}

Point operator+(const double &a, const Point &p){
    return Point(a + p.x(), a + p.y());
}

Point operator-(const double &a, const Point &p){
    return Point(a - p.x(), a - p.y());
}

Point operator*(const double &a, const Point &p){
    return Point(a / p.x(), a / p.y());
}

Point operator/(const double &a, const Point &p){
    return Point(a * p.x(), a * p.y());
}

bool Point::operator>(const Point &p){
    if (this->x() > p.x())
        return true;
    if (this->y() > p.y())
        return true;
    return false;
}

bool Point::operator==(const Point &p){
    return this->x() == p.x() && this->y() == p.y();
}

bool Point::operator!=(const Point &p2){
    return !(*this == p2);
}

bool Point::operator<(const Point &p){
    return !(*this > p) && !(*this == p);
}

bool Point::operator<=(const Point &p){
    return !(*this > p);
}

bool Point::operator>=(const Point &p){
    return !(*this < p);
}

void Point::operator+=(const Point &p){
    this->setCor(this->x() + p.x(), this->y() + p.y());
}

void Point::operator-=(const Point &p){
    this->setCor(this->x() - p.x(), this->y() - p.y());
}

void Point::operator*=(const Point &p){
    this->setCor(this->x() * p.x(), this->y() * p.y());
}

void Point::operator/=(const Point &p){
    this->setCor(this->x() / p.x(), this->y() / p.y());
}

void Point::operator+=(const double &a){
    this->setCor(this->x() + a, this->y() + a);
}

void Point::operator-=(const double &a){
    this->setCor(this->x() - a, this->y() - a);
}

void Point::operator*=(const double &a){
    this->setCor(this->x() * a, this->y() * a);
}

void Point::operator/=(const double &a){
    this->setCor(this->x() / a, this->y() / a);
}

istream &operator>>(istream &input, Point &p){
    input >> p._x >> p._y;
    return input;
}

ostream &operator<<(ostream &output, const Point &p){
    output << '(' << p._x << ", " << p._y << ')';
    return output;
}

Point Point::operator++(){
    this->setCor(this->x() + 1, this->y() + 1);
    return *this;
}

Point Point::operator++(int){
    Point p = *this;
    this->setCor(this->x() + 1, this->y() + 1);
    return p;
}

Point Point::operator>>(const Point &p){
    return Point( int ( this->x() ) >> int ( p.x() ), int ( this->y() ) >> int ( p.y() ) );
}

Point Point::operator<<(const Point &p){
    return Point( int ( this->x() ) << int (p.x() ), int (this->y() ) << int ( p.y() ) );
}

Point Point::operator~(){
    return Point( ~(int ( this->x() ) ), ~( int ( this->y() ) ) );
}

Point Point::operator&(const Point &p){
    return Point( int (this->x()) & int (p.x()), int (this->y()) & int (p.y()) );
}

Point Point::operator|(const Point &p){
    return Point( int (this->x()) | int (p.x()), int (this->y()) | int (p.y()) );
}

Point Point::operator^(const Point &p){
    return Point( int (this->x()) ^ int (p.x()), int (this->y()) ^ int (p.y()) );
}

void Point::operator>>=(const Point &p){
    this->setCor( int (this->x()) >> int (p.x()), int (this->y()) >> int (p.y()) );
}

void Point::operator<<=(const Point &p){
    this->setCor( int (this->x()) << int (p.x()), int (this->y()) << int (p.y()) );
}

void Point::operator&=(const Point &p){
    this->setCor( int (this->x()) & int (p.x()), int (this->y()) & int (p.y()) );
}

void Point::operator|=(const Point &p){
    this->setCor( int (this->x()) | int (p.x()), int (this->y()) | int (p.y()) );
}

void Point::operator^=(const Point &p){
    this->setCor( int (this->x()) ^ int (p.x()), int (this->y()) ^ int (p.y()) );
}

double Point::operator[](const int &k){
    return (this->x() + this->y()) * k;
}

void Point::operator()(const int &x, const int &y){
    this->setCor(this->x() * x, this->y() * y);
}

int main(){
    return 0;
}

در این کد Prototype توابع و تعریفشان کنار هم است. معمولا این دو را در دو فایل جداگانه ذخیره می کنند؛ یکی با پسوند h و یکی با پسوند cpp. برنامه های زیر به ترتیب Point.h و Point.cpp هستند.

#ifndef POINT_H
#define POINT_H

#include <iostream>
#include <cstdio>

using namespace std;

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

    private:

        double _x, _y;
        
    public:

        Point(double = 0, double = 0);

        double x() const;
        double y() const;

        void setX(double);
        void setY(double);

        void print();
        void setCor(double, double);

        Point operator+(const Point&);
        Point operator-(const Point&);
        Point operator*(const Point&);
        Point operator/(const Point&);

        Point operator+(const double&);
        Point operator-(const double&);
        Point operator/(const double&);
        Point operator*(const double&);
        friend Point operator+(const double&, const Point&);
        friend Point operator-(const double&, const Point&);
        friend Point operator*(const double&, const Point&);
        friend Point operator/(const double&, const Point&);

        bool operator==(const Point&);
        bool operator!=(const Point&);
        bool operator>(const Point&);
        bool operator<(const Point&);
        bool operator>=(const Point&);
        bool operator<=(const Point&);

        void operator+=(const Point&);
        void operator-=(const Point&);
        void operator*=(const Point&);
        void operator/=(const Point&);
        void operator+=(const double&);
        void operator-=(const double&);
        void operator*=(const double&);
        void operator/=(const double&);

        Point operator++();
        Point operator++(int);

        Point operator>>(const Point&);
        Point operator<<(const Point&);
        Point operator~();
        Point operator&(const Point&);
        Point operator|(const Point&);
        Point operator^(const Point&);

        void operator>>=(const Point&);
        void operator<<=(const Point&);
        void operator&=(const Point&);
        void operator|=(const Point&);
        void operator^=(const Point&);

        void operator()(const int&, const int&);
        double operator[](const int&);

};

#endif

#include "Point.h"

Point::Point(double x, double y){
    this->setX(x);
    this->setY(y);
}

void Point::setX(double x){
    this->_x = x;
}

void Point::setY(double y){
    this->_y = y;
}

double Point::x() const{
    return this->_x;
}

double Point::y() const{
    return this->_y;
}

void Point::print(){
    printf("(%g, %g)", this->x(), this->y());
}

void Point::setCor(double x, double y){
    this->_x = x;
    this->_y = y;
}

Point Point::operator+(const Point &p2){
    return Point(this->x() + p2.x(), this->y() + p2.y());
}

Point Point::operator-(const Point &p2){
    return Point(this->x() - p2.x(), this->y() - p2.y());
}

Point Point::operator*(const Point &p2){
    return Point(this->x() * p2.x(), this->y() * p2.y());
}

Point Point::operator/(const Point &p2){
    return Point(this->x() / p2.x(), this->y() / p2.y());
}

Point Point::operator+(const double &a){
    return Point(this->x() + a, this->y() + a);
}

Point Point::operator-(const double &a){
    return Point(this->x() - a, this->y() - a);
}

Point Point::operator*(const double &a){
    return Point(this->x() * a, this->y() * a);
}

Point Point::operator/(const double &a){
    return Point(this->x() / a, this->y() / a);
}

Point operator+(const double &a, const Point &p){
    return Point(a + p.x(), a + p.y());
}

Point operator-(const double &a, const Point &p){
    return Point(a - p.x(), a - p.y());
}

Point operator*(const double &a, const Point &p){
    return Point(a / p.x(), a / p.y());
}

Point operator/(const double &a, const Point &p){
    return Point(a * p.x(), a * p.y());
}

bool Point::operator>(const Point &p){
    if (this->x() > p.x())
        return true;
    if (this->y() > p.y())
        return true;
    return false;
}

bool Point::operator==(const Point &p){
    return this->x() == p.x() && this->y() == p.y();
}

bool Point::operator!=(const Point &p2){
    return !(*this == p2);
}

bool Point::operator<(const Point &p){
    return !(*this > p) && !(*this == p);
}

bool Point::operator<=(const Point &p){
    return !(*this > p);
}

bool Point::operator>=(const Point &p){
    return !(*this < p);
}

void Point::operator+=(const Point &p){
    this->setCor(this->x() + p.x(), this->y() + p.y());
}

void Point::operator-=(const Point &p){
    this->setCor(this->x() - p.x(), this->y() - p.y());
}

void Point::operator*=(const Point &p){
    this->setCor(this->x() * p.x(), this->y() * p.y());
}

void Point::operator/=(const Point &p){
    this->setCor(this->x() / p.x(), this->y() / p.y());
}

void Point::operator+=(const double &a){
    this->setCor(this->x() + a, this->y() + a);
}

void Point::operator-=(const double &a){
    this->setCor(this->x() - a, this->y() - a);
}

void Point::operator*=(const double &a){
    this->setCor(this->x() * a, this->y() * a);
}

void Point::operator/=(const double &a){
    this->setCor(this->x() / a, this->y() / a);
}

istream &operator>>(istream &input, Point &p){
    input >> p._x >> p._y;
    return input;
}

ostream &operator<<(ostream &output, const Point &p){
    output << '(' << p._x << ", " << p._y << ')';
    return output;
}

Point Point::operator++(){
    this->setCor(this->x() + 1, this->y() + 1);
    return *this;
}

Point Point::operator++(int){
    Point p = *this;
    this->setCor(this->x() + 1, this->y() + 1);
    return p;
}

Point Point::operator>>(const Point &p){
    return Point( int ( this->x() ) >> int ( p.x() ), int ( this->y() ) >> int ( p.y() ) );
}

Point Point::operator<<(const Point &p){
    return Point( int ( this->x() ) << int (p.x() ), int (this->y() ) << int ( p.y() ) );
}

Point Point::operator~(){
    return Point( ~(int ( this->x() ) ), ~( int ( this->y() ) ) );
}

Point Point::operator&(const Point &p){
    return Point( int (this->x()) & int (p.x()), int (this->y()) & int (p.y()) );
}

Point Point::operator|(const Point &p){
    return Point( int (this->x()) | int (p.x()), int (this->y()) | int (p.y()) );
}

Point Point::operator^(const Point &p){
    return Point( int (this->x()) ^ int (p.x()), int (this->y()) ^ int (p.y()) );
}

void Point::operator>>=(const Point &p){
    this->setCor( int (this->x()) >> int (p.x()), int (this->y()) >> int (p.y()) );
}

void Point::operator<<=(const Point &p){
    this->setCor( int (this->x()) << int (p.x()), int (this->y()) << int (p.y()) );
}

void Point::operator&=(const Point &p){
    this->setCor( int (this->x()) & int (p.x()), int (this->y()) & int (p.y()) );
}

void Point::operator|=(const Point &p){
    this->setCor( int (this->x()) | int (p.x()), int (this->y()) | int (p.y()) );
}

void Point::operator^=(const Point &p){
    this->setCor( int (this->x()) ^ int (p.x()), int (this->y()) ^ int (p.y()) );
}

double Point::operator[](const int &k){
    return (this->x() + this->y()) * k;
}

void Point::operator()(const int &x, const int &y){
    this->setCor(this->x() * x, this->y() * y);
}

کد main هم به صورت زیر در می آید.

#include "Point.h"

int main(){
    return 0;
}

نکته: دستورهایی که در Point.h مشاهده می کنید (ifndef، define و endif)، برای این هستند که اگر در دو فایل متفاوت از Point.h استفاده شد، این کد یک بار include شود.

حالا برای کامپایل این برنامه چه کار می کنیم. مثلا برای کامپایل همین برنامه ۳ فایل داریم؛ فایل های Point.h و Point.cpp و همچنین فایل main.cpp. از این دستور ها برای به دست آمدن فایل های Object (با پسوند o) استفاده می کنیم؛

g++ -c Point.cpp
g++ -c main.cpp

حالا دو فایل جدید داریم؛ Point.o و main.o. حالا این ها را به هم link می کنیم؛

g++ -o MAIN main.o Point.o

یکی از فایده های استفاده از این روش تسریع در روند کامپایل است. شما به جای این که هر دفعه Point.cpp را کامپایل کنید، یک بار آن را کامپایل می کنید و دیگر از فایل Point.o استفاده می کنید.

فعلا موضوع خاص دیگری باقی نمانده است؛ جلسه ی بعد این موضوع را کامل خواهیم کرد.