12.5 Constructors


https://www.learncpp.com/cpp-tutorial/constructors/
すべてのメンバーがpublicの場合、list-initiationを使用してクラスを初期化することもできます.
class Foo
{
public:
    int m_x {};
    int m_y {};
};

int main()
{
    Foo foo { 6, 7 }; // list-initialization

    return 0;
}
ただし、member variableがprivateの場合、外部からアクセスできません
では、どのように初期化すればいいのでしょうか.

Constructors


コンストラクション関数は特殊なメンバー関数です
classオブジェクトの作成時に呼び出された
他のメンバー関数とは異なり、コンストラクション関数には正しいネーミングルールがあります.
1. Constructors must have the same name as the class (with the same capitalization)
2. Constructors have no return type (not even void)

Default constructors and default initialization


パラメータのないコンストラクション関数をdefaultコンストラクション関数と呼ぶ

Direct- and list-initialization using constructors with parameters


パラメータを使用して初期化することもできます
#include <cassert>

class Fraction
{
private:
    int m_numerator {};
    int m_denominator {};

public:
    Fraction() // default constructor
    {
         m_numerator = 0;
         m_denominator = 1;
    }

    // Constructor with two parameters, one parameter having a default value
    Fraction(int numerator, int denominator=1)
    {
        assert(denominator != 0);
        m_numerator = numerator;
        m_denominator = denominator;
    }

    int getNumerator() { return m_numerator; }
    int getDenominator() { return m_denominator; }
    double getValue() { return static_cast<double>(m_numerator) / m_denominator; }
};
上のコンストラクション関数にはdefaultコンストラクション関数と
parameterの構造関数も存在する
Fraction fiveThirds{ 5, 3 }; // List initialization, calls Fraction(int, int)
Fraction threeQuarters(3, 4); // Direct initialization, also calls Fraction(int, int)
上のように歌うこともできます.
Fraction six{ 6 }; // calls Fraction(int, int) constructor, second parameter uses default value of 1
defaultパラメータが1つ使用されているので、上記のようにコンストラクション関数を呼び出すこともできます.

Reducing your constructors


parameter defalut valueを使用して冗長なdefaultコンストラクタを省略することもできます.
#include <cassert>

class Fraction
{
private:
    int m_numerator {};
    int m_denominator {};

public:
    // Default constructor
    Fraction(int numerator=0, int denominator=1)
    {
        assert(denominator != 0);

        m_numerator = numerator;
        m_denominator = denominator;
    }

    int getNumerator() { return m_numerator; }
    int getDenominator() { return m_denominator; }
    double getValue() { return static_cast<double>(m_numerator) / m_denominator; }
};

An implicitly generated default constructor


定義したclassにconstructorが存在しない場合
c++自動定義default constructor
暗黙構造関数と呼ぶ

Classes containing classes


classが別のclassをメンバーとする場合
どのクラス構築関数が最初に呼び出されますか?
#include <iostream>

class A
{
public:
    A() { std::cout << "A\n"; }
};

class B
{
private:
    A m_a; // B contains A as a member variable

public:
    B() { std::cout << "B\n"; }
};

int main()
{
    B b;
    return 0;
}
上記のコードでは、bがdefaultコンストラクタとしてインスタンス化すると、
出力は次のとおりです.
A
B
上の結果を考えると合理的です.BのconstructorがAメンバーを使用できる場合.
すなわち,Bのコンストラクション関数が呼び出される前に,Aを生成しなければならない.

Constructor notes


コンストラクション関数はオブジェクトの作成ではありません
objectの作成時に初期化を支援すると理解されます
関数を構築する目的は
  • は、オブジェクト
  • を正しい方法で作成する方法を定義する.
  • は、生成するオブジェクト
  • を初期化する.