質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C++11

C++11は2011年に容認されたC++のISO標準です。以前のC++03に代わるもので、中枢の言語の変更・修正、標準ライブラリの拡張・改善を加えたものです。

Q&A

3回答

1747閲覧

コンストラクタ以外でインスタンス生成時にのみ値を設定できるようにする方法

suittizihou

総合スコア27

C++11

C++11は2011年に容認されたC++のISO標準です。以前のC++03に代わるもので、中枢の言語の変更・修正、標準ライブラリの拡張・改善を加えたものです。

0グッド

0クリップ

投稿2021/04/10 15:41

###実現したいこと
templateを使ってクラスのインスタンスを生成しているのですが、クラスを定義するときコンストラクタにおまじないのような引数を追加する必要があり、それを回避したいと思っています。

現在使用しているコードです(一部抜粋)

C++

1// シーンの親クラス 2class Scene{ 3public: 4Scene(const std::string& sceneName, const UINT sceneID) : 5m_SceneName{ sceneName }, m_SceneID{ sceneID } {} 6 7private: 8std::string m_SceneName{}; 9UINT m_SceneID{}; 10}; 11 12// サンプルシーン(ユーザーが定義するクラス) 13class SampleScene : public Scene { 14public: 15// おまじない引数 16SampleScene(const std::string& sceneName, const UINT sceneID) : 17Scene(sceneName, sceneID) {} 18}; 19 20// シーンを追加したりするクラス 21class SceneManager { 22public: 23template<class T> 24void AddScene(const std::string& sceneName) { 25 std::shared_ptr<T> scene = std::make_shared<T>(sceneName, m_Scenes.size()); 26 m_Scenes[sceneName] = scene; 27} 28 29private: 30std::map<std::string, std::shared_ptr<Scene>> m_Scenes; 31}; 32

###思いついた解決方法
・Sceneクラスに名前とIDを設定するprivateな関数を作成して、friendでSceneManagerにのみ公開する方法

個人的にfriendはコードが一気に汚れるので使いたくありません。。。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

コンストラクタは引数なしとし、インスタンス生成後に一度だけm_SceneName,m_SceneIDを設定できるようにしたいということでしょうか。
そうであるならば、未設定の場合にのみ設定できるメソッドを追加すれば達成できるのでは?
以下ではm_SceneNameが最大値の場合を未設定時の値としていますが、最大値も使用したいなら別途フラグを追加で。

C++

1// シーンの親クラス 2class Scene { 3public: 4 Scene() : m_SceneID(std::numeric_limits<UINT>::max()) {} 5 void SetSceneInfo(const std::string& sceneName, const UINT sceneID) 6 { 7 if (std::numeric_limits<UINT>::max() != m_SceneID) 8 { 9 m_SceneName = sceneName; 10 m_SceneID = sceneID; 11 } 12 } 13 14private: 15 std::string m_SceneName; 16 UINT m_SceneID; 17}; 18 19// サンプルシーン(ユーザーが定義するクラス) 20class SampleScene : public Scene { 21public: 22 SampleScene() : Scene() {} 23}; 24 25// シーンを追加したりするクラス 26class SceneManager { 27public: 28 template<class T> 29 void AddScene(const std::string& sceneName) { 30 std::shared_ptr<Scene> scene = std::make_shared<T>(); 31 scene->SetSceneInfo(sceneName, m_Scenes.size()); 32 m_Scenes[sceneName] = scene; 33 } 34 35private: 36 std::map<std::string, std::shared_ptr<Scene>> m_Scenes; 37};

投稿2021/04/11 14:30

編集2021/04/11 14:52
SHOMI

総合スコア4079

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

  • 「Sceneおよびそれを継承した型ではScene::Scene(const std::string& sceneName, const UINT sceneID)による初期化をしなければならない」という形の設計
  • templateでインスタンスを生成するという利点がよくわからない実装

の2つが余計なしがらみを生じさせているという話ならば,(この不自由な形を採るべき特段の理由があるのでもなければ)この両方を見直せばよいのでは.


Sceneに本当に必要なのは,名前とIDを「取得できること」なのかもしれません.
であれば,例えば,Sceneは

C++

1class Scene 2{ 3public: 4 virtual const std::string &GetName() = 0; 5 virtual UINT GetID() = 0; 6};

みたいな形の方が妥当なのかもしれません.

SceneManager::AddSceneは,tmplateにせずとも,単に
void AddScene( std::shared_ptr<Scene> spScene ) とか void AddScene( std::unique_ptr<Scene> &&upScene ) とかで問題ないかもしれません.

この形であれば,SampleSceneの生成方法の実装形態には何のしがらみも無くなります.
(まぁ,名前とIDの解決手段が何かしら必要なことには変わりはありませんが)

投稿2021/04/11 02:42

編集2021/04/11 03:15
fana

総合スコア11996

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yumetodo

2021/04/11 03:25

ちょっと寝かせて考えてみましたけど別に今のコードもそんなに悪いと思わないんですよね・・・。
fana

2021/04/12 01:17

どんな形にしようが,どこぞで名前とIDを指定してやる必要があるわけで,それに最も相応しいのはコンストラクタだと思う…んだけども,それが嫌だという話(?)なので, インスタンス生成~SceneManagerの管理に入る までの部分をもっと自由にしてやって,管理下に入って以降は名前とIDに関してReadOnlyな型で扱えばそこが書き換えられる心配も無かろう,と.
guest

0

そのコンストラクタで追加でなにかする気がないなら単に書かなければいいような。

投稿2021/04/10 18:36

yumetodo

総合スコア5852

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

suittizihou

2021/04/10 23:07

シーン本体にもシーン名とIDを持たせておきたいのですが、名前とIDは生成時に1回セットするだけでそれ以降変えられるとバグが発生してしまうのでコンストラクタで設定していました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問