topazの遊び場

いろいろやってみる

そろそろC++やるぞパート5 クラス入門2

そろそろC++やります

そろそろC++をやります。そろそろC++をやりたいからです。
何回やるかはわかりません。基礎を理解するまではやろうと思います。

という感じでやっています。

※ 初心者がメモレベルで記録するので、技術記事としてはお力になれないかもしれません。

内容

前回、クラスはどんな感じで書くのか軽く触れてみたので、今回はMicrosoftのドキュメントを見ていきます。

クラスの構文

ドキュメントを見る人や講義で扱った人はこのような書き方を見たことがあると思います。自分もこのようなものを大学の講義で行いました。

[template-spec]
class [ms-decl-spec] [tag [: base-list ]]
{
   member-list
} [declarators];

[ class ] tag declarators;

鉤括弧[ ]で囲われているところは省略可能な部分です。

つまり、最小の([ ]を無くした)クラスは、class{ };member-listのみで構成されます。

class
{
  member-list
}:

これは、無名クラス(匿名クラスとも呼ぶ)として内部クラスで使用されるそうです。(参考

class COuter {
public:
    class {
    public:
        int m_num;
    };
    COuter(int num) : m_num(num) {}
    int Get () const { return m_num; }
};

この、最小構成のクラスに[ ]の部分を追加したものがよく見るクラスになります。
これから各構成要素について、わかりやすいところから、見ていきます。

tag

// 再掲
[template-spec]
class [ms-decl-spec] [tag [: base-list ]]
{
   member-list
} [declarators];

tagはクラス名のことを指しています。

class MyClass
{
};

こちらの場合はMyClassがtagになります。
tagは、クラスのスコープ内で予約語となり、メンバ変数名や関数名として用いることができません。クラス名はコンストラクタやデストラクタに使われます。

: base-list

// 再掲
[template-spec]
class [ms-decl-spec] [tag [: base-list ]]
{
   member-list
} [declarators];

[ class ] tag declarators;

これは継承を表します。C#と同じ:の後に継承元のクラスを書きます。 

class Vector2
{
public:
    int x;
    int y;
};

class Vector3 : public Vector2
{
public:
    int z;
};

継承することで、継承前のpublicなメンバに外部から参照することができます。

int main()
{
    Vector3 vec;
    vec.x = 100;
    vec.y = 200;
    vec.z = 300;

    cout << "x = " << vec.x << endl;
    cout << "y = " << vec.y << endl;
    cout << "z = " << vec.z << endl;

    return 0;
}
// Output:            
// x = 100
// y = 200
// z = 300

class Vector3 : public Vector2の部分で継承を行なっており、継承時のアクセス修飾子によって継承元のクラスのメンバや変数の継承後のアクセス範囲が変化します。
ここでは、継承という機能の存在だけを把握し、詳細については継承をまとめた時に、深く考えます。

declarator

クラスの定義時に1つ以上のインスタンスを生成することができます。
class {}の後に、インスタンス名を列挙します。

class MyClass
{
public:
    int v = 10;
} a, b;

int main()
{
    cout << a.v << endl;
    cout << b.v << endl;
    return 0;
}

declarator に関しては詳しい説明がされている記事がなく、これ以上のことが分かりませんでした。

template-spec

// 再掲
[template-spec]
class [ms-decl-spec] [tag [: base-list ]]
{
   member-list
} [declarators];

[ class ] tag declarators;

template-specは、テンプレートを指定できます。
おおまかには、テンプレートは、多言語でいうジェネリクスのような役割のものです。(厳密には異なりますがここでは触れません)
template <typename {T} >と書きます。

template <typename V>
class MyClass
{
public:
    V v = 10;
};

使用する方は、ジェネリクスにとても似ていて、class名<template名>で型を記載します。

int main()
{
    MyClass<int> intClass;
    intClass.v = 8.0 / 5;

    MyClass<float> floatClass;
    floatClass.v = 8.0 / 5;

    cout << intClass.v << endl;
    // Output : 1
    cout << floatClass.v << endl;
    // Output : 1.6
    return 0;
}

クラス用のテンプレートだけでなく、関数用のテンプレートなどもあるので、テンプレートについて詳しくはまた別の機会に触れたいと思います。

ms-decl-spec

// 再掲
[template-spec]
class [ms-decl-spec] [tag [: base-list ]]
{
   member-list
} [declarators];

[ class ] tag declarators;

ms-decl-specストレージクラスを指定するキーワードです。
オブジェクトの有効期間やリンケージ、メモリの場所を制御することができます。
これは少し難しいないようなので、初級を脱出したら、また考えたいと思います。ストレージクラス

member-list

// 再掲
[template-spec]
class [ms-decl-spec] [tag [: base-list ]]
{
   member-list
} [declarators];

[ class ] tag declarators;

そして最後は、member-listです。お馴染みのメンバー関数などに触れたいのですが、member-listだけでこの項目に分かれています。

  • 特殊なメンバー関数。
  • メンバー関数の概要。
  • 組み込みの型やその他のユーザー定義型を含む、変更可能な静的データ メンバー。
  • オペレーター
  • 入れ子にされたクラス宣言および)
  • 共用体
  • 列挙型。
  • ビット フィールド。
  • フレンド。
  • エイリアスと typedef。

そのため、member-listだけ次回に回したいと思います。

参考リスト

感想

JavaC#オブジェクト指向を中心に触っていたため、Classはとても楽しみでした。大まかな書き方は同じで、ジェネリクスがなくてtemplateだったり、さまざまな修飾子がつけられる点はとても拡張性がありそうです。
あと、今更なのですがドキュメントって実際に手を動かしてコード書いて、なるほど!と思いながらやるのは楽しいです。
自分がいろんな言語を触ってたので、それとの比較にもなってそれもまたおもしろいです。

次回は続きの class の member-list を行おうと思います。