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

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

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

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

3回答

10362閲覧

C++クラスの、Privateなメンバ変数を隠蔽したい

Unity-chan

総合スコア20

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2017/04/24 09:38

###前提・実現したいこと
C++のクラス宣言をヘッダーとCPPファイルに分けて行う場合、Privateメンバ変数もヘッダーに記述しなければなりません。Privateにも関わらず外部から丸見え状態なのがもやもやするので、PimplのようにCPPファイルの方へ記述し、外部から隠蔽したいと考えているのですが、やり方がわかりません。

###該当のソースコード
今回の質問には直接関係ないとは思いますが、具体的に隠蔽したい箇所を示すためにも開発中のソースコードをのせます。

C++

1#ifndef __FrameRateInfo_h__ 2#define __FrameRateInfo_h__ 3 4#include <chrono> 5 6class FrameRateInfo{ 7public: 8 FrameRateInfo(int fps = 60); 9 10 bool UpdateFrameCount(); 11 void Wait1Frame(); 12 void GetFrameRate(double *frameRate); 13 14 15// この部分を外部から隠蔽したい 16private: 17 std::chrono::high_resolution_clock::time_point m_startTime; 18 int m_frameCount; 19 float m_frameRate; 20 static const int AVERAGE_COUNT = 60; 21 int FPS; 22}; 23 24#endif

C++

1#include <math.h> 2#include <Windows.h> 3#include <iostream> 4#include <chrono> 5#include "FrameRateInfo.h" 6 7using std::cout; 8using std::endl; 9using namespace std::chrono; 10 11// フレームレートを設定するコンストラクタ 12FrameRateInfo::FrameRateInfo(int fps){ 13 m_frameCount = 0; 14 m_frameRate = 0; 15 FPS = fps; 16} 17 18bool FrameRateInfo::UpdateFrameCount(){ 19 switch (m_frameCount){ 20 // フレームカウントが1ならば、その時刻を記憶する 21 case 0: 22 m_startTime = high_resolution_clock::now(); 23 break; 24 25 // 指定フレームカウントになったら、現在のフレームレートを平均から計算する 26 case AVERAGE_COUNT: 27 auto endTime = high_resolution_clock::now(); 28 m_frameRate = 1000 / (duration_cast<milliseconds>(endTime - m_startTime).count() / (float)AVERAGE_COUNT); 29 m_frameCount = 0; 30 m_startTime = endTime; 31 break; 32 } 33 34 m_frameCount++; 35 36 return true; 37} 38 39void FrameRateInfo::Wait1Frame(){ 40 switch (m_frameCount){ 41 // フレームカウントが1ならば、その時刻を記憶する 42 case 0: 43 m_startTime = high_resolution_clock::now(); 44 break; 45 46 // 指定フレームカウントになったら、現在のフレームレートを平均から計算する 47 case AVERAGE_COUNT: 48 auto endTime = high_resolution_clock::now(); 49 m_frameRate = 1000 / (duration_cast<milliseconds>(endTime - m_startTime).count() / (float)AVERAGE_COUNT); 50 m_frameCount = 0; 51 m_startTime = endTime; 52 break; 53 } 54 55 m_frameCount++; 56 57 58 59 auto tookTime = high_resolution_clock::now() - m_startTime; //かかった時間 60 auto waitTime = m_frameCount * 1000 / FPS - (DWORD)duration_cast<milliseconds>(tookTime).count(); //待つべき時間 61 if (waitTime > 0){ 62 Sleep(waitTime); //待機 63 } 64} 65 66// 現在のフレームレートを取得する 67void FrameRateInfo::GetFrameRate(double *frameRate){ 68 *frameRate = m_frameRate; 69} 70

###試したこと
Pimplイディオムというものを用いれば、関数ならヘッダーに記述することなく外部から隠蔽することが出来るらしいのですが、変数はできないのかやり方が悪いのか期待通りの動作にはなりませんでした。

###補足情報(言語/FW/ツール等のバージョンなど)
Visual Studio 2013 for Windows Desktop

回答よろしくお願いします。

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

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

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

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

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

guest

回答3

0

pimplでやれますよ。

C++

1// counter.h 2class counter_impl; 3 4class counter { 5public: 6 counter(); 7 ~counter(); 8 void increment(); 9 int get() const; 10private: 11 counter_impl* pimpl; 12};

C++

1// counter.cpp 2class counter_impl { 3public: 4 counter_impl() : count(0) {} 5 void increment() { ++count; } 6 int get() const { return count; } 7private: 8 int count; 9}; 10 11counter::counter() : impl(new counter_impl) {} 12counter::~counter() { delete impl; } 13void coutner::increment() { impl->increment(); } 14int get() const { return impl->get(); }

投稿2017/04/24 09:59

episteme

総合スコア16614

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

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

0

通常のprivateとして使えるものを使うのは原理的に難しい、と思います。

というのも、privateメンバといえどもメモリを消費するので、ヘッダできちんと宣言しておかないと、どれだけの容量をこのクラスが消費するのかわからなくなってしまうからです。

クラス内に別なクラスへのポインタを持たせて、別なクラスは不完全型にしておいてそちらの詳細は公開しない、というような手段を取る必要があると思います。

投稿2017/04/24 09:51

maisumakun

総合スコア145121

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

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

episteme

2017/04/24 18:54

見えてたからってメモリ消費量がわかるわけじゃないですよー class foo { int* ptr; // ptr = new int[10000] されてるかも知んないよ? ... };
maisumakun

2017/04/24 22:03

newで取った分はポインタしか入らないので、「クラス自体」の容量としては固定ですよね。
episteme

2017/04/24 22:26

pimplでもメンバはポインタいっこですよ? 「クラス自体」の容量としては固定ですよね。 てかそもそもコンパイル時に大きさの定まらないclass/structは作れないっしょ。
guest

0

epistemeさん、maisumakunさんの意見に補足

お二方とも正しいことをおっしゃってますが、言葉が足りなくて、質問者さんには多分伝わっていない。

質問者さんの言葉を「忖度」すると、多分、質問者さんは、公開するファイルに変数も書いているのだと思います。pimplイディオムでは、「公開する関数」と、「実体へのポインタ」のみを公開するファイルに書きます。変数はすべて、実装部分にのみ記載します。これにより、利用者は実装の詳細を一切知ることがなくなります。

通常のprivateとして使えるものを(省略)
というのも、(省略)

1段落目はよく分かりませんでしたが、2段落目からソンタックすると、privateメンバまで記載がないと領域の確保ができない、という御趣旨だと思います。これは、静的領域に確保するという前提の限りでは正しいです。静的領域は、コンパイル時にスタック等の構造が決まりますから、オブジェクトのレイアウトが判明していないと領域が確保できません。
しかし、pimplイディオムでは、実装はヒープ上に確保するので、利用側ではサイズが判明する必要がありません(実装部では必要)。公開用のオブジェクトのレイアウトさえ分かれば、利用可能となるわけです。

長々と書きましたが要約すると、「pimplイディオムで大丈夫、変数の公開は無理だしpimplイディオム使う意味ないから」ということです。

投稿2017/04/25 07:35

編集2017/04/25 13:15
majiponi

総合スコア1720

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問