Cpp クラス オーバーロード

提供:yonewiki

C++に戻る


本来の表記は「C++(Cpp) クラス オーバーロード」です。この記事に付けられた題名はテンプレート:記事名の制約から不正確なものとなっています。

※このページではC++にのみ存在する機能として、記事タイトルがC++ クラス オーバーロードになっています。

クラス オーバーロード

 同じメンバ関数名に対して引数の異なるモノを作成することをオーバーロードするとか、多重定義をすると言います。受け取った引数によって処理を変えたり、少しだけ引数を加工して、結局は共通のプログラムを動かすための架け橋にしたりすることが出来ます。いろいろな引数で対応して便利な機能を提供することが出来ます。これはコンストラクタに対しても行えるモノです。


 例えば、以下のようになります。

cpp (COverloadSum.h)

#ifndef __COVERLOADSUM_H_YONET__
#define __COVERLOADSUM_H_YONET__

#if _msc_ver > 1000 //Microsoft VisualStudio C++ Ver4.0 Over Only Enable
#pragma once
#endif
class COverloadSum{
private:
    int m_iSum;
    int* m_piData;
    void m_fSum(int* iArgVal);

public:
    void COverloadSum(int iArgVal1, int iArgVal2);
    void COverloadSum(int* piArgVal, int iSizeArgVal);
    void COverloadSum(float fArgVal1, float fArgVal2);
    void COverloadSum(float* pfArgVal,int iSizeArgVal);
    int  Get();
};
#endif

cpp (COverloadSum.cpp)

#include <cstdio>
#include "COverloadSum.h"

using namespace std;
void COverloadSum::COverloadSum(int iArgVal1, int iArgVal2){
    m_piData = new int[2];
    m_piData[0] = iArgVal1;
    m_piData[1] = iArgVal2;
    m_fSum( m_piData, (int)sizeof(int)*2);//sizeof演算子の戻り値はsize_t型=unsigned int型です。符号を無視するキャストなので安全なキャスト。2,147,483,647より大きな数にならないこと
}

void COverloadSum::COverloadSum(int* piArgVal, int iSizeArgVal){
    m_fSum( m_piArgVal, iSizeArgVal);
}

void COverloadSum::COverloadSum(float fArgVal1, float fArgVal2){
    m_piData = new int[2];
    m_piData[0] = ceil(fArgVal1);
    m_piData[1] = ceil(fArgVal2);

    m_fSum( m_piData, (int)sizeof(float)*2);
}

void COverloadSum::COverloadSum(float* pfArgVal, int iSizeArgVal){
    for(int iScan = 0; i <  iSizeArgVal / (int)sizeof (float) ; iScan++){
        m_piData[iScan] = pfArgVal[iScan];
    }
    m_fSum( m_piData, iSizeArgVal);
}

void mf_Sum(int* piArgVal, int iSizeArgVal){
    for(int iScan = 0; i < iSizeArgVal / (int)sizeof(int) ; iScan++){
        m_iSum = m_iSum + piArgVal[iScan];
    }
}
int  Get(){
    return m_iSum;
}


cpp (OverloadSumMain.cpp)

#include <cstdio>
#include "COverloadSum.h"

using namespace std;
int main(){
    COverloadSum objCOverloadSum_Int_Int(5, 5);
    COverloadSum objCOverloadSum_Float_Float(13.3, 7.25);

    int piDataArr[4] = { 3, 7, 9, 10 };
    COverloadSum objCOverloadSum_pInt(piDataArr, (int)sizeof(piDataArr));

    float pfDataArr[5] = { 3.2, 5.4, 8.2, 13.4, 42.5 };
    COverloadSum objCOverloadSum_pFloat(pfDataArr, (int)sizeof(pfDataArr));

    printf("IntInt=%d, pInt=%d, FloatFloat=%d, pFloat=%d,\n",
        objCOverloadSum_Int_Int.Get(),
        objCOverloadSum_pInt.Get(),
        objCOverloadSum_Float_Float.Get(),
        objCOverloadSum_pFloat.Get()
    )
}


8行目~11行目(ヘッダファイル部)

    void COverloadSum(int iArgVal1, int iArgVal2);
    void COverloadSum(int* piArgVal, int iSizeArgVal);
    void COverloadSum(float fArgVal1, float fArgVal2);
    void COverloadSum(float* pfArgVal,int iSizeArgVal);

 ここが、多重定義(Overload:オーバーロード)部分で、同じ名前のメンバ関数がズラッと書かれていますが、それぞれ異なる型の引数を受け取るように定義されています。これでも対応している引数の取り方は少ない方です。もっともっといろんな引数を受け渡したいパターンもあると思います。もっともっと汎用性を持たせるためには、後で紹介する予定のSTL(スタンダードテンプレートライブラリ)という技術を使う方法もあります。一個人が作るコードが、そこまで汎用性をもったクラスである必要は低いかもしれませんが、理解しておかなければ、いざという時につぶしが効かないということを心にして、こういったプログラミングの学習は進めて行くべきだと思います。

102行目~131行目(クラスプログラム部)

 そうして、具体的な処理内容を記述します。ここではint型の2つの引数を受け取る関数はint型の配列関数にしてint型の配列を全て足し合わせる関数を読んでいます。m_fSum関数はすべてのオーバーロード関数から呼び出されるプライベートなクラスです。int型配列を受け取る関数はそのままm_fSumへ受け流す感じになり、float型はint型に変換+小数点以下の切り上げという方法を実施して足しています。float型配列を受け取る関数はそれぞれをint型に変換しつつ、受け渡すためのint配列を構成します。


 このように異なる引数を受け取った関数がよりよい機能であるためにオーバーロードを行います。よくみかけるものです。可変長の引数を受け取る関数もこの仕組みを使えば作成可能です。


 まぁでも疲れる。まじで疲れる。このサンプルプログラムも疲れる。そういうことです。あんまり使いたくないなぁ。最低限の技術しか使おうとしない自分のような、さぼりプログラマには敷居が少し高いな。飲食店の入り口がマンションのドアみたいになっている店くらい敷居が高い。


 この記事のプログラムでは、ヘッダファイルの読み込みを少し念入りに書きました。いろんな記事を読んでいる内に忘れてしまうこともあると思いますが、#pragma once はマイクロソフト独自の技術で、Ver4.0以上で使えるものだからです。他のコンパイラでも使えることもありますが、バグを持っていたりと不完全なこともあるため、使わない方がいいとも言われています。インクルードガードも使っていますが、この方法で読み込みが避けられたとしても、#pragma onceで読み込まれない方が遥かにコンパイル速度が速くなります。


C++に戻る