Archive for 1月 24th, 2010

C++でのクラスと構造体

前回C++のクラスは構造体の拡張であるという話し。
まず一般的な構造体から見ていきましょう、と。

#include <iostream>
#include <string.h>
using namespace std;

struct hoge
{
    int a;
    double b;
    char c[128];
} foo;

int main()
{
    hoge* pFoo = &foo;

    foo.a = 100;
    foo.b = 3.141592674;
    strcpy(foo.c, "構造体のテストじゃ~。");

    cout << "直接参照:\n" <<
        "foo.a = " << foo.a <<
        "\nfoo.b = " << foo.b <<
        "\nfoo.c = " << foo.c << endl;
    cout << "間接参照:\n" <<
        "pFoo->a = " << pFoo->a <<
        "\npFoo->b = " << pFoo->b <<
        "\npFoo->c = " << pFoo->c << endl;

    cout << "\n\n";

    pFoo->a = 500;
    pFoo->b = 1.05;
    strcpy(pFoo->c, "ポインタから更新じゃじゃ~。");

    cout << "直接参照:\n" <<
        "foo.a = " << foo.a <<
        "\nfoo.b = " << foo.b <<
        "\nfoo.c = " << foo.c << endl;
    cout << "間接参照:\n" <<
        "pFoo->a = " << pFoo->a <<
        "\npFoo->b = " << pFoo->b <<
        "\npFoo->c = " << pFoo->c << endl;

    return 0;
}

まぁ、これは普通に読めること前提。
一応実行結果はこれ。

直接参照:
foo.a = 100
foo.b = 3.14159
foo.c = 構造体のテストじゃ~。
間接参照:
pFoo->a = 100
pFoo->b = 3.14159
pFoo->c = 構造体のテストじゃ~。

直接参照:
foo.a = 500
foo.b = 1.05
foo.c = ポインタから更新じゃじゃ~。
間接参照:
pFoo->a = 500
pFoo->b = 1.05
pFoo->c = ポインタから更新じゃじゃ~。

で、これをそっくりクラスで書くと下記の通り。

#include <iostream>
#include <string.h>
using namespace std;

class hoge
{
    public:
        int a;
        double b;
        char c[128];
} foo;

int main()
{
    hoge* pFoo = &foo;

    foo.a = 100;
    foo.b = 3.141592674;
    strcpy(foo.c, "クラスのテストじゃ~。");

    cout << "直接参照:\n" <<
        "foo.a = " << foo.a <<
        "\nfoo.b = " << foo.b <<
        "\nfoo.c = " << foo.c << endl;
    cout << "間接参照:\n" <<
        "pFoo->a = " << pFoo->a <<
        "\npFoo->b = " << pFoo->b <<
        "\npFoo->c = " << pFoo->c << endl;

    cout << "\n\n";

    pFoo->a = 500;
    pFoo->b = 1.05;
    strcpy(pFoo->c, "ポインタから更新じゃじゃ~。");

    cout << "直接参照:\n" <<
        "foo.a = " << foo.a <<
        "\nfoo.b = " << foo.b <<
        "\nfoo.c = " << foo.c << endl;
    cout << "間接参照:\n" <<
        "pFoo->a = " << pFoo->a <<
        "\npFoo->b = " << pFoo->b <<
        "\npFoo->c = " << pFoo->c << endl;

    return 0;
}

こんな風にpublic:をつけるだけ。
感がいい人はわかってると思うけど、構造体でもprivate:を付けてしまえばクラスっぽくなると言うね。
となると、構造体でもメンバ関数(メソッド)を用意することができる。

同じようなコードにすると下記なような感じになる。

#include <iostream>
#include <string.h>
using namespace std;

class CFoo
{
    private:
        int a;
        double b;
        char c[128];
    public:
        CFoo():a(0),b(0.0)
        {
            for (int i = 0; i < 128; ++i)
                c[i] = '\0';
        }
        ~CFoo() {}
        int setA(int num)
        {
            a = num;
            return 0;
        }
        int setB(double num)
        {
            b = num;
            return 0;
        }
        int setC(char* szStr)
        {
            if (strlen(szStr) > 127) {
                return 1;
            }
            strcpy(c, szStr);
            return 0;
        }

        int getA() { return a; }
        double getB() { return b; }
        char* getC() { return c; }
};

struct Bar_t
{
    private:
        int a;
        double b;
        char c[128];
    public:
        Bar_t():a(0),b(0.0)
        {
            for (int i = 0; i < 128; ++i)
                c[i] = '\0';
        }
        ~Bar_t() {}
        int setA(int num)
        {
            a = num;
            return 0;
        }
        int setB(double num)
        {
            b = num;
            return 0;
        }
        int setC(char* szStr)
        {
            if (strlen(szStr) > 127) {
                return 1;
            }
            strcpy(c, szStr);
            return 0;
        }

        int getA() { return a; }
        double getB() { return b; }
        char* getC() { return c; }
};

int main()
{
    CFoo obj;
    Bar_t obj2;

    cout << "初期化時のクラス:\n" <<
        "\tobj.getA() = " << obj.getA() <<
        "\n\tobj.getB() = " << obj.getB() <<
        "\n\tobj.getC() = " << obj.getC() << endl;
    cout << "初期化時の構造体:\n" <<
        "\tobj2.getA() = " << obj2.getA() <<
        "\n\tobj2.getB() = " << obj2.getB() <<
        "\n\tobj2.getC() = " << obj2.getC() << endl;

    obj.setA(10000);
    obj.setB(11.11);
    obj.setC("我が輩の年齢は10万と26歳である、フハハハハ!");

    obj2.setA(-1);
    obj2.setB(42.195);
    obj2.setC("オラ、ワクワクしてきたぞ!");

    cout << "代入時のクラス:\n" <<
        "\tobj.getA() = " << obj.getA() <<
        "\n\tobj.getB() = " << obj.getB() <<
        "\n\tobj.getC() = " << obj.getC() << endl;
    cout << "代入時の構造体:\n" <<
        "\tobj2.getA() = " << obj2.getA() <<
        "\n\tobj2.getB() = " << obj2.getB() <<
        "\n\tobj2.getC() = " << obj2.getC() << endl;

    return 0;
}

何となく命名規則をそれっぽくしてみたけど、こんな感じ?
ほとんどというか、private:とpublic:を付けてしまえば両方とも一緒という結果。

そんだけ。

Post to Twitter

, , ,

No Comments

C++でのメンバ変数として、動的オブジェクトを作る

C++を勉強していて何が困ったって、メインで動的にメモリ領域をとる方法はたくさん載っているのに、クラスのメンバ変数を動的にとる方法がなかなか載っていない。
と言うわけで、いろいろ試行錯誤した結果、下記のようになった。

テスト用コード

#include <iostream>
#include <string.h>
using namespace std;

class hoge
{
    public:
        char* szStr;
        hoge(char* szNewStr)
        {
            szStr = new char[strlen(szNewStr)];
            strcpy(szStr, szNewStr);
        }
        ~hoge() { delete szNewStr; }
};

int main()
{
    char szStr[] = {"ばかやろ~~~~~~~~~~~~~~~"};

    cout << szStr << endl;
    cout << "end" << endl;

    cout << strlen(szStr) << endl;

    hoge* obj;
    obj = new hoge(szStr);

    cout << "\ntest\n";
    cout << szStr << endl;

    delete obj;

    return 0;
}

実行結果。

ばかやろ~~~~~~~~~~~~~~~
end
57

test
ばかやろ~~~~~~~~~~~~~~~

まず、hogeなるクラスを定義します、と。
そのメンバ変数に動的に確保したい型のポインタを置きます、と。
それをコンストラクタなり、なんなりでnewしてあげるとそこにで動的に確保される、と。
ちなみに、ここで言う「型」というのは文字通りの型じゃなくても良くて、クラスでも良い。
なぜかというと、C++でのクラスは構造体を拡張したものだから。

その詳細はまた別の記事にて。

そんだけ。

Post to Twitter

, , ,

No Comments

Bad Behavior has blocked 19 access attempts in the last 7 days.