データメンバのクラスをpublicで持ってもいいのでしょうか?

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
豆電球

データメンバのクラスをpublicで持ってもいいのでしょうか?

#1

投稿記事 by 豆電球 » 4年前

C++を始めてもうすぐ一ヶ月になり、今までの知識とこれから得る知識を1つのプロジェクトに
入れ込んでいこうと思い哺乳類クラスをトップとするものを作り始めました。
哺乳類→動物→猫があり、猫レベルのクラスにstring nameを持たせ、setname、getnameの関数を
作ると、同様の関数をこのレベルのクラスに作ることになり、それを避ける為に上位クラスに
nameを持たせようとも思ったのですが、哺乳類クラスや動物クラスがnameを持つことが
ピンときませんでした。
そこでNameクラスを作ってデータメンバとして持たせることを考えましたが、publicでなければ
結局Nameクラスのデータメンバにアクセスする為の関数をpublicに作らなければなりません。
最初に戻ってしまいました。
「クラスの責任はそのクラスが負う」というのなら、猫クラスはNameクラスをpublicで持っても
いいのかなと思って、何かないのかなと思って検索してみたのですが、クラスのデータメンバも
privateで持ち、その関数をpublicでというコードばかりでした。
やはりデータメンバはクラスであってもpublicにしないというのが基本のようです。

皆さんはこのような場合、どのような方法を取られるのでしょうか、よろしくお願い致します。

豆電球

Re: データメンバのクラスをpublicで持ってもいいのでしょうか?

#2

投稿記事 by 豆電球 » 4年前

すみません、哺乳類→猫 です。
変なのを入れてしまいました。

Rittai_3D
記事: 525
登録日時: 7年前

Re: データメンバのクラスをpublicで持ってもいいのでしょうか?

#3

投稿記事 by Rittai_3D » 4年前

豆電球 さんが書きました:哺乳類クラスや動物クラスがnameを持つことが
ピンときませんでした。
動物などの抽象的なものが具体的な名前を持つのが不自然、ということでしょうか。
でしたら、nameという具体的なものを動物クラスで持たせず、派生先で持たせて、親クラスに具体的なものを扱う為の仮想関数を書いておけばよいのではないでしょうか。

コード:

class Animal
{
public:
    /* コンストラクタ・デストラクタは省略 */

    virtual void SetName( const std::string& name ) = 0;
    virtual std::string GetName() const = 0;
};

class Cat : public Animal
{
    std::string    m_name;
public:
    /* コンストラクタ・デストラクタは省略 */

    virtual void SetName( const std::string& name ) override
    {
        m_name = name;
    }

    virtual std::string GetName() const override
    {
        return m_name;
    }
};
こんな感じで。
豆電球 さんが書きました:「クラスの責任はそのクラスが負う」というのなら、猫クラスはNameクラスをpublicで持っても
いいのかなと思って、何かないのかなと思って検索してみたのですが、クラスのデータメンバも
privateで持ち、その関数をpublicでというコードばかりでした。
やはりデータメンバはクラスであってもpublicにしないというのが基本のようです。
触れる必要のないものには触れないようにする、が基本でしょう。
少なくともわたしは、データメンバはpublicにはしません。
publicにするのは、const / constexpr を使用した定数などです。
それ以外はgetterを介して取得します。

内容を読み間違えていましたら申し訳ないです。
初心者です

豆電球

Re: データメンバのクラスをpublicで持ってもいいのでしょうか?

#4

投稿記事 by 豆電球 » 4年前

Rittai_3Dさん、ありがとうございます。
やはり、アクセサを書くというのが基本ですなのですね。
猫、犬などそのレベルのクラスに同様の関数を書かずにNameクラスで処理できないかと
考えてしまいました。

コード:

//	mainStart.cpp
#pragma warning(disable:4996)
#include <iostream>
#include "mammal.h"

using namespace std;

int main()
{
	Cat tama("たま");
	cout << tama.name.getName() << endl;	//	CatのnameをpublicにすればOKだけど。。。

	::system("pause");
	return 0;
}

コード:

//	mammal.h
//	class--> Mammal,Person,Cat
//	class--> include"has_a.h"(Name)
#pragma once
#include <iostream>
#include <string>
#include "has_a.h"

using namespace std;

//	Mammal class
class Mammal
{
private:
	int sex;
public:
	void setSex(int a_sex);
	int getSex()const;
};

//	Cat class-----
class Cat :public Mammal
{
protected:
private:
public:
	Name name;	//	has_a	Nameクラスの責任はNameクラスが負うのでPublicでも問題ないのでしょうか?
public:
	Cat(string a_name);// : name(a_name);は実装に書く。プロトタイプには書かない。
};

//	Person class-----
class Person :public Mammal
{
private:
	Name name;	//	has_a
public:

};
//	inline--------------インライン関数はヘッダーファイルに書く。
//	Mammal実装+++++
inline void Mammal::setSex(int a_sex)
{
	if (((unsigned int)a_sex) > 2){ sex = 0; }	// 0=不明、1=男(雄)、2=女(雌)
	sex = a_sex;
}

inline int Mammal::getSex()const
{
	return sex;
}

//	Animal実装+++++


//	Cat実装+++++
inline Cat::Cat(string a_name) : name(a_name)	//	Nameクラスのコンストラクタを呼び出し
{
	//	他は何もしない
}


//	Person実装+++++

コード:

#pragma once
#pragma warning(disable:4996)
#include <iostream>
#include <string>

using namespace std;

//	Name class-----
class Name
{
private:
	string name;
public:
	Name(string a_name);
	void setName(string a_name);
	string getName()const;
};

//	inline ------------------------------------------------------------
//	Name実装+++++
inline Name::Name(string a_name)	//	名前を引数に取るコンストラクタ
{
	name = a_name;
}
inline void Name::setName(string a_name)
{
	name = a_name;
}

inline string Name::getName()const
{
	return name;
}
こうすれば、同様の関数を猫、犬などのクラスレベルに書かなくてもいいかなと思ってしまったのです^^;
この考え方はダメそうですね^^;

Rittai_3D
記事: 525
登録日時: 7年前

Re: データメンバのクラスをpublicで持ってもいいのでしょうか?

#5

投稿記事 by Rittai_3D » 4年前

豆電球 さんが書きました:

コード:

 cout << tama.name.getName() << endl;    //  CatのnameをpublicにすればOKだけど。。。
これ、ぱっと見た時に違和感を感じませんか?個人的には"name.getName()"でnameが被っているのが気になります。

コード:

tama.getName();
で十分意味が通りますし。
豆電球 さんが書きました:

コード:

 Name name;  //  has_a   Nameクラスの責任はNameクラスが負うのでPublicでも問題ないのでしょうか?
よくないと思います。
例えば、

コード:

// いろいろ省略
int main()
{
    Cat tama( "たま" );
    tama.name = Name { "Rittai_3D" };

    cout << tama.name.getName() << endl;
}

としたらどうでしょうか。
簡単に変数が書きかえられることはよくないです。隠ぺいしましょう。
オフトピック
ヘッダファイルに using namespace std; はちょっと・・・。
初心者です

アバター
usao
記事: 1584
登録日時: 7年前

Re: データメンバのクラスをpublicで持ってもいいのでしょうか?

#6

投稿記事 by usao » 4年前

「名前のある哺乳動物」を作るのではだめなんでしょうか.

哺乳動物→名前のある哺乳動物→猫
哺乳動物→名前のある哺乳動物→犬
哺乳動物→河童 (あえて名前をもたないとする良い例が思いつかない…)

オフトピック
>やはりデータメンバはクラスであってもpublicにしないというのが基本のようです。

「みんながやってるから → 自分もそうやる」
とかじゃなくて
「そのようにしている理由のようなものを自分で把握したから → 結果として自分もそうやる」
という形でありたいですね.

豆電球

Re: データメンバのクラスをpublicで持ってもいいのでしょうか?

#7

投稿記事 by 豆電球 » 4年前

Rittai_3D さん、物凄く納得です^^

usaoさん、ありがとうございます。
まだまだ、やっと真似をするというレベルなのでこれから頑張ります^^

Rittai_3D さん、usaoさん、ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る