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

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

新規登録して質問してみよう
ただいま回答率
85.48%
オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

C++

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

Q&A

8回答

17003閲覧

C++ オブジェクト指向 staticの使用について

_Victorique__

総合スコア1392

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

C++

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

0グッド

3クリップ

投稿2017/06/08 07:18

編集2017/06/08 08:19

C++前提で話します。

static修飾子がありますが、classを使っていてstaticが必要だと思ったことがありません。
staticでできることは理解していますがやはり使う機会はありません。
そもそもオブジェクト指向的にstaticって矛盾していませんか?
オブジェクト指向を完全に理解しているわけではないので全く見当違いなことを言っていたら申し訳ないです。
もしオブジェクト指向的におかしくないのなら、どのような場面でstaticは便利なのでしょうか?

追記

staticが必要になってくるというのは分かりました。
では、積極的にstaticにした方が良いのでしょうか?
そこまで複雑なコードを書いてきていないからかもしれませんが、staticにしても問題ないという変数や関数に遭遇していません(遭遇しているが気づいていないかもしれませんが)。どうしてもstaticに違和感があります。

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

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

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

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

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

guest

回答8

0

こんにちは。

staticなメンバは、名前空間内に定義したグローバル変数、グローバル関数と大差ありません。
つまり、これらはオブジェクト指向プログラミングというよりは、多くの場合は手続き型プログラミングと思います。(シングルトン・バターン等、オブジェクト指向プログラミングに分類した方が良いものもあります。)

では、オブジェクト指向プログラミングさえあれば、手続き型プログラミングが完全に不要かと言うとそんなことはありません。やはり必要な場面はでてきます。
その時、クラスのstaticメンバで実装するのか、通常のグローバル関数/グローバル変数で実装するのかは、大差はないように感じます。
よりクラスと強く結びついた機能ならstaticメンバでしょうし、例えば、他のクラスもサポートするようなあまりクラスとの結びつきが強くないものはグローバル関数/変数を選択するだろうと思います。


【追記への回答】

では、積極的にstaticにした方が良いのでしょうか?

staticと非static、どちらかが良いかはその要件で決定できると思います。
クラスをインスタンス化する度に必要なメモリなら非staticメンバ変数です。
その非staticメンバ変数を操作する関数なら概ね非staticメンバ関数でしょう。(こちらは例外があるかもしれません。)

クラスに対して1つだけ存在して欲しいメモリならstaticメンバ変数です。
一切の非staticメンバをアクセスしないなら概ねstaticメンバ関数でしょう。(たまたまアクセスしていないだけで、本質的にはアクセスしても可笑しくない場合は非staticで実装することもあるでしょう。)

投稿2017/06/08 07:46

編集2017/06/08 12:47
Chironian

総合スコア23272

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

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

0

下記質問の回答にて様々な意見を得られると思います。

※C++に限った話ではないですが

投稿2017/06/08 07:38

m.ts10806

総合スコア80850

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

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

0

どうしてもstaticに違和感があります。

逆からの意見になりますが、たまにクラスのメンバ変数、関数を一切参照しないメンバ関数を見たりします。
これには私は違和感を感じます。
なんでただの関数にしないのか?せめてstaticな関数にしてくれと。

投稿2017/06/08 09:32

can110

総合スコア38256

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

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

0

コールバックされる関数はstaticでないといけませんよね。非staticなメンバー関数は暗黙でthisポインタが渡されるので、クラスのインスタンスと無関係なところからコールされるようにはできません。

また、全てのインスタンスにかかわる設定をstaticなメンバー変数として保存しておいたりします。
ファイルを出力するクラスを作ったとして、改行をLFにするかCR+LFにするかはファイルごとに異なることよりもすべてのファイルで同じ設定を使うことが多いと思います(テキストエディタのようなソフトでは別ですが)。そうであれば、設定を変更した場合に、全てのインスタンスの設定を変えるよりも、staticなメンバー変数の内容を変えるほうが楽になります。

投稿2017/06/08 07:55

m-take

総合スコア249

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

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

0

オブジェクト指向の最も重要な要素である「カプセル化」の観点から見たら、むしろstaticはオブジェクト指向的に無くてはならないものだと思います。
staticがなければグローバル変数や手続き型の関数を使わざるを得なくなってしまいます。

どうしてもstaticに違和感があります。

クラスに紐付いた情報をカプセル化したものがstaticメンバ。
そのstaticメンバを扱うための関数がstaticメソッドと考えればスッキリしませんか?

では、積極的にstaticにした方が良いのでしょうか?

staticメンバとインスタンスに属するメンバは、役割が根本的に違いますので交換可能ではありません。
すべてのインスタンスで共通の値を持ちたい場合はstaticメンバ、インスタンスごとに個別の値を持ちたい場合は非staticメンバになります。

微々たるものですが、適切にstaticにした方がthisポインタを経由したりスタックに積まないので速度的にもメモリ的にも有利です。

投稿2017/06/08 11:27

編集2017/06/08 14:34
pashango2

総合スコア930

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

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

0

そもそもオブジェクト指向的にstaticって矛盾していませんか?

同感です。
class ベースのオブジェクト指向なら全部インスタンス化しろよ
という意見もあるでしょうが、それだとコスト的に見合わない
場合があるので、苦肉の策って感じなのでしょうか。

使わずに済むならそうすれはせいいと思いますし、
必要な局面が出てきたら使う。
そんくらいのスタンスでいいと思いますよ~

投稿2017/06/08 09:02

takasima20

総合スコア7458

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

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

0

一般的な場面は他の方が述べているようですのでちょっと変わり種の用途としては、テンプレートと組み合わせて型を識別するような値を作りたいというような場合ですね。

説明しづらいので簡単なコードを示します。

cpp

1#include <iostream> 2 3template<class T> struct foo { 4 static int tag; 5 const int* tag_pointer = &tag; 6 template<class U> 7 bool operator==(foo<U> x) { 8 return tag_pointer == x.tag_pointer; 9 } 10}; 11 12template<class T> int foo<T>::tag = 0; 13 14int main(void) { 15 foo<int> x, y; 16 foo<double> z; 17 18 std::cout << "x==y = " << (x==y) << std::endl; 19 std::cout << "x==z = " << (x==z) << std::endl; 20}

このときテンプレートクラス foo の型引数 T は使われません。 いわゆる幽霊型 (Phantom type) です。 しかし T に当て嵌められた型ごとに foo は実体化されるので、上述の例では static なメンバである foo<T>::tagfoo<int>::tagfoo<double>::tag のふたつが作られることになります。 もちろんそれぞれ違う場所に作られるのでその変数のアドレスは型ごとに異なります。

普通は type_info を使う方が簡単なのですが、本格的なメタプログラミングでは活用したりもするみたいです。

投稿2017/06/08 08:16

SaitoAtsushi

総合スコア5444

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

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

0

他にも、クラスのメンバー関数を_beginthreadする場合はstaticであることが要求されます。以下のように別のstaticなメンバー関数を噛ませて非staticなメンバー関数をスレッドとして実行する方法がありますが、結局staticな関数は必要なわけで。
オブジェクト指向的にどうのこうというより、現実問題として必要な場面があるということになるかと。

C++

1class Test { 2:private 3 HANDLE thread; // スレッドハンドル 4 5 // スレッド開始 6 void threadStart(){ 7 thread = (HANDLE) _beginthread( 8 &test::executeLauncher, // ランチャを起動 9 0, 10 this); 11 } 12 13 // ランチャ 14 static void executeLauncher(void* args){ 15 // 無理やりtest*型にキャストして、本命の処理を実行する。 16 reinterpret_cast<test*>(args)->execute(); 17 } 18 19 // 本命の処理(非staticメンバ変数) 20 void execute(){ 2122 } 23}; 24 25main(){ 26 Test test = new Test(); 27 // スレッドで、staticではないメンバ変数execute()が実行 28 test->threadStart(); 29}

投稿2017/06/08 08:11

PineMatsu

総合スコア3579

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問