★クラスのコピーを禁止★


今回はクラスのコピーを禁止する方法を説明します。

複雑では無いので、簡単なサンプルを作ります。

<sample program cpp071-01>

#include <iostream>

class Player {
public:

    Player();

    Player(const int hp, const int mp);

    void Show() const;

private:

    int m_hp;
    int m_mp;
};

int main()
{
    Player player1(100, 50);

    Player player2;

    player2 = player1;       //代入

    player2.Show();

    Player player3(player2); //コピーコンストラクタ

    player3.Show();

    return 0;
}

Player::Player()
{

}

Player::Player(const int hp, const int mp) : m_hp(hp), m_mp(mp)
{

}

void Player::Show() const
{
    std::cout << "HP = " << m_hp << " : MP = " << m_mp << std::endl;
}

<実行結果>

HP = 100 : MP = 50
HP = 100 : MP = 50
続行するには何かキーを押してください・・・

Playerクラスを用意しました。

player1を作り、コンストラクタ関数で初期値をセットしています。

player2を作り、player1を代入しました。

問題無くコピー出来ている事が分かります。

player3はコピーコンストラクタを使ってplayer2をコピーして作りました。

これも問題無くコピー出来ています。


コピーの禁止


この2種類のコピーを禁止するコードを追加します。

<sample program cpp071-02>

#include <iostream>

class Player {
public:

    Player();

    Player(const int hp, const int mp);

    void Show() const;

private:

    int m_hp;
    int m_mp;

    Player(const Player &);
    Player& operator=(const Player &);
};

int main()
{
    Player player1(100, 50);

    Player player2;

    player2 = player1;

    player2.Show();

    Player player3(player2);

    player3.Show();

    return 0;
}

Player::Player()
{

}

Player::Player(const int hp, const int mp) : m_hp(hp), m_mp(mp)
{

}

void Player::Show() const
{
    std::cout << "HP = " << m_hp << " : MP = " << m_mp << std::endl;
}

<コンパイル結果>

error C2248: 'Player::operator =': private メンバー (クラス 'Player' で宣言されている) にアクセスできません。
note: 'Player::operator =' の宣言を確認してください
note: 'Player' の宣言を確認してください
error C2248: 'Player::Player': private メンバー (クラス 'Player' で宣言されている) にアクセスできません。
note: 'Player::Player' の宣言を確認してください
note: 'Player' の宣言を確認してください

コンパイル時にエラーが発生しました。


まず、クラスを見てみます。

private:

    int m_hp;
    int m_mp;

    Player(const Player &);
    Player& operator=(const Player &);

privateにコピーコンストラクタと代入演算子のオーバーロードのプロトタイプ宣言を書きました。

これだけでコピーが禁止されます。

privateに書いた変数などは、このクラスの内部でしか使えませんので、main関数など他の場所では使えなくなります。

関数も例外ではありません。

privateに書いた関数は、このクラスの中でしか使えない関数になります。

エラーの内容を見てみましょう。

error C2248: 'Player::operator =': private メンバー (クラス 'Player' で宣言されている) にアクセスできません。

「=」演算子がprivateなのでアクセス出来ない、と書いてあります。

また、

error C2248: 'Player::Player': private メンバー (クラス 'Player' で宣言されている) にアクセスできません。

コピーコンストラクタもprivateなのでアクセス出来ません。


前回、関数への値渡しやコンテナへのpushもコピーだと書きました。

実際に確かめてみましょう。


関数への値渡し


では、関数への値渡しを試します。

何か1つ関数を作って、引数としてクラスを渡してみましょう。

<sample program cpp071-03>

#include <iostream>
#include <vector>

class Player {
public:

    Player();

    Player(const int hp, const int mp);

    void Show() const;

private:

    int m_hp;
    int m_mp;

    Player(const Player &);
    Player& operator=(const Player &);
};

void ShowStatus(const Player player);

int main()
{
    Player player(100, 50);

    ShowStatus(player);

    return 0;
}

Player::Player()
{

}

Player::Player(const int hp, const int mp) : m_hp(hp), m_mp(mp)
{

}

void Player::Show() const
{
    std::cout << "HP = " << m_hp << " : MP = " << m_mp << std::endl;
}

void ShowStatus(const Player player)
{
    player.Show();
}

<コンパイル結果>

error C2248: 'Player::Player': private メンバー (クラス 'Player' で宣言されている) にアクセスできません。
note: 'Player::Player' の宣言を確認してください
note: 'Player' の宣言を確認してください

コンパイル時にエラーが発生しました。


関数へ値渡しを行う場合もコピーが行われますが、コピーは禁止されていますのでエラーになりました。

「アドレス渡し」や「参照渡し」であれば問題無く行えます。


コンテナへのpush


次にコンテナへのpushを試してみます。

main関数で「ベクタ」を用意し、クラスをpush_backしてみます。

<sample program cpp071-04>

#include <iostream>
#include <vector>

class Player {
public:

    Player();

    Player(const int hp, const int mp);

    void Show() const;

private:

    int m_hp;
    int m_mp;

    Player(const Player &);
    Player& operator=(const Player &);
};

int main()
{
    Player player(100, 50);

    std::vector<Player> vecPlayer;

    vecPlayer.push_back(player);

    return 0;
}

Player::Player()
{

}

Player::Player(const int hp, const int mp) : m_hp(hp), m_mp(mp)
{

}

void Player::Show() const
{
    std::cout << "HP = " << m_hp << " : MP = " << m_mp << std::endl;
}

<コンパイル結果>

error C2248: 'Player::Player': private メンバー (クラス 'Player' で宣言されている) にアクセスできません。
note: 'Player::Player' の宣言を確認してください
note: 'Player' の宣言を確認してください

コンパイル時にエラーが発生しましたが、長いので最初の3行だけ書きました。


コンテナへのpushは、内部でクラスをコピーしています。

今回はコピーを禁止していますので、エラーになりました。


このようにポインタを持ったクラスを扱う際には、細かい部分まで注意して扱ってください。


次へ

戻る

目次へ