最速怪談選手権

はじめまして。
C++のライブラリ(静的、動的問わず)について
いくつか教えてください。

たとえば、1つのクラスで定義した以下のようなライブラリ
(まずは、静的 or 動的は問いません)があるとします。
class library
{
library();
~library();
public
GetX();
private
 int a;
}

さらに、実行プログラムMain.exeが存在し、このMain.exeは、
上記ライブラリをリンクしているものとします。

このとき、Main.exe内では、libraryをnewすることもなく、
library::GetX();と呼べるわけですが、

(1)コンストラクタはいつ呼ばれているのでしょうか?
(2)(1)に関係しそうですが、Main.exeがマルチスレッドの場合に、
   Main threadとsub threadから呼ぶときに、ライブラリのコンテキスト?インスタンス?は
   同じなのでしょうか?それともスレッドごとに作られるのでしょうか?

ご存知のかたいらっしゃいましたら教えてください。
説明不足があればご指摘ください。宜しくお願いいたします。

A 回答 (4件)

>こちらですが、高度なというのはどういう意味でしょうか?


>linux環境でもプロセス間では割り当てメモリが
>異なるような気がいたしますが、
>もし開発環境で異なるということは、
>実際に、開発を始める場合にこのあたりについては
>OSを調べればよいのでしょうか?

基本的にOSの問題ととらえてよいと考えます。
今あるPC用のOSであれば、Win/Linux/Free BSDなど
は皆"高度"であると考えてよいと思います。

組み込み用途だと、直接物理アドレスにアクセスすることも
多いですよね。
むしろ、PCのように論理アドレスが割り振られるほうが
珍しいのでは?
という感じです。
    • good
    • 0
この回答へのお礼

何度もお答えいただきありがとうございます。

直接物理アドレスにアクセスするような場合には、
また変わってくるということですね。
だいぶ理解が深まりました。

お礼日時:2009/05/26 20:24

>static関数はstatic関数だけしか呼べないというのも合っていますでしょうか?



厳密にいうと違いますね。
クラスメンバ関数限定での話であれば
staticメンバ関数は非staticメンバ関数を呼べないので、
static関数しか呼べないという言い方もできます。

ただし、static関数でもクラスに所属しない関数は自由に呼べます。
その意味で、厳密にはクラスのstatic関数は、クラスのstatic関数
しか呼べないわけではありません。

>class内で定義したstatic関数(library::GetX();)とグローバル関数は
>単に名前が違うものと思えばよいのでしょうか?

基本的な扱い方は、クラス名::をつけられたグローバル関数と
考えてもよいと思います。
ただし、あくまでもクラスに所属する以上
アクセス制限(public, protected, private)からは逃れられません。

publicなstaticメンバ関数は
(呼び出す側からすれば)
クラス::をつけて呼ぶことがお約束のグローバル関数と考えてよいと思います。

>たとえば、プロセスA、Bがあり、Aのほうで定義(合っていますか?)した
>static関数Aがあった場合、
>プロセスBからstatic関数Aは呼べるのでしょうか?

また、理解に苦しむのですが....
そもそも、プロセスAとプロセスBはお互い関数コールなどは
”基本的には"できません。
プロセス間通信など、特別な手法が必要です。

私が勝手に想像するに
複数のプロセス間でクラスstatic関数を通じてクラスのメンバ変数を
共有できるのか?

ということがお知りになりたいのではと思います。

具体的にコードを提示しましょう

class c
{
protected:
static int m_Count = 0;
public:
static void Inc() {m_Count++;}
static int GetCount() {return m_Count;}
}

こんなクラス cがあります。
プロセスX内で
c::Inc();
と実行した後
c::GetCount()は1を戻します。
これ以後
プロセスXではc::Inc()を一切呼ばないものとします。

その後、プロセスYで
c::GetCount()
を呼んだら、答えはどうなるか?

初期値のまま0が戻るのか、
それとも
プロセスXの実行結果を反映して
1が戻るのか?

こういうことではないでしょうか?

答えは前者(0)です。
クラスのstaticメンバであっても
プロセス境界を越えて共有することはできません。

ちょっと低レベル(マシン寄りという意味)な話をさせてもらうと
プロセスにはそれぞれ、別々のメモリが割り当てられ、
お互いに、他のプロセスのメモリをアクセスすることは
不可能です。

プロセスXでいうアドレス0x00001234は
物理メモリの0xAAAA1234を指しているかも知れません。

プロセスYでアドレス0x00001234に書き込んでも
物理メモリの0xAAAA1234には(通常)書き込まれません。
なぜなら
プロセスYにはプロセスXが使用するメモリとは重ならない
領域が割り当てられるからです。
プロセスYの0x00001234は物理メモリの
0xBBBB1234
に割り当てられるかもしれません。

ソースコード上では
char* p;
p = 0x00001234;
というコードがプロセスX、Y両者にあれば
*pを通じて情報が共有できそうですが、
(実際、MSDOSなどの時代にはできていました)
Windowsのような”高度な"OSでは不可能です。

それにより
1つのプロセスが誤動作を起こしても
他のプロセスに影響が及ぶ可能性を
(0とはいかないが)低減させているのです。

この回答への補足

とても分かりやすいご説明ありがとうございます。

> 私が勝手に想像するに
> 複数のプロセス間でクラスstatic関数を通じてクラスのメンバ変数を
> 共有できるのか?

こちら、そのとおりです。
クラスstatic関数だけでなく、グローバル関数についても
お聞きしたかったところですが、
プロセス間ではスレッド間とは異なり割り当てられているメモリが
異なるということでアクセスすることはできないということだと思います。

> ソースコード上では
> char* p;
> p = 0x00001234;
> というコードがプロセスX、Y両者にあれば
> *pを通じて情報が共有できそうですが、
> (実際、MSDOSなどの時代にはできていました)
> Windowsのような”高度な"OSでは不可能です。

こちらですが、高度なというのはどういう意味でしょうか?
linux環境でもプロセス間では割り当てメモリが異なるような気がいたしますが、
もし開発環境で異なるということは、
実際に、開発を始める場合にこのあたりについてはOSを調べればよいのでしょうか?
それともプログラミング言語を調べるべきなのでしょうか?
それともコンパイルの設定などで変更できるものなのでしょうか?

補足日時:2009/05/23 11:52
    • good
    • 0

ライブラリとクラスの概念を混同していませんか?


この2つには全く何の関係もありません。
そこを明確にしましょう。

>1つのクラスで定義した以下のようなライブラリ

表現があやしいですが...
1つのクラスだけで構成されるライブラリ
と理解しておきます。

>上記ライブラリ
class library を含むライブラリ
と理解します。

>このとき、Main.exe内では、libraryをnewすることもなく、
>library::GetX();と呼べるわけですが、

えーーーーーーーーーーー
本当ですか?
基本的には無理です。
C++の言語仕様からいって不可能です。

GetX() がstaticなら可能ですが
staticじゃないですよね?

ライブラリでも一般のソースでもそうですが
クラス名::メンバ関数名
の形式でコールできるのは
1)派生クラス内部から基本クラスのメンバを呼ぶ場合
2)static関数を呼ぶ場合

に限定されます。

staticをつけ忘れたという前提で話します。
(違っていたらごめんなさい)

>(1)コンストラクタはいつ呼ばれているのでしょうか?

static関数を呼び出すのにオブジェクトは必要ありません。
(必要ないのでクラス名::の形式で呼べるのです)
コンストラクタが呼ばれなくても動作します。
その代わり、staticメンバ関数からはstaticメンバ変数にしか
アクセスできません。
staticでない”普通の"メンバ変数はオブジェクトが必要です。
(オブジェクト毎に違う値を取り得ます)
従って、オブジェクトの存在を前提としない
static関数からはアクセスできないのです。

>(2)(1)に関係しそうですが、Main.exeがマルチスレッドの場合に、
>   Main threadとsub threadから呼ぶときに、
>ライブラリのコンテキスト?インスタンス?は
>   同じなのでしょうか?それともスレッドごとに作られるのでしょうか?

先も述べたようにstatic関数にインスタンスは不要なのです。
これは、シングルスレッド、マルチスレッドとまったく違う次元の話です。
強いて言えば
マルチスレッドでもシングルスレッドでもインスタンスなしでアクセスできます。
staticメンバ関数が内部でstaticメンバ変数にアクセスしている場合
(よくあることです)
マルチスレッドの場合、排他をかけておかないと
正常動作しない可能性があります。

この回答への補足

ご指摘いただいたとおりstaticではないといけないですね。
説明不足のところいろいろお察しいただき感謝しております。

> static関数を呼び出すのにオブジェクトは必要ありません。
>(必要ないのでクラス名::の形式で呼べるのです)
> コンストラクタが呼ばれなくても動作します。

こちらですが、
static関数はstatic関数だけしか呼べないというのも合っていますでしょうか?
ちょっとstatic関数の理解ができていないかもしれません。
class内で定義したstatic関数(library::GetX();)とグローバル関数は
単に名前が違うものと思えばよいのでしょうか?

> 強いて言えば
> マルチスレッドでもシングルスレッドでもインスタンスなしでアクセ> スできます。

マルチスレッドではプロセス内の同じstatic関数を
どちらのスレッドからも実行できるということですね。

> staticメンバ関数が内部でstaticメンバ変数にアクセスしている場合
> (よくあることです)
> マルチスレッドの場合、排他をかけておかないと
> 正常動作しない可能性があります。

staticなものはそのプロセス単位?でただひとつしか存在しない、
存在することができないということだと思いますが、
異なるプロセス間ではどうなのでしょうか?
たとえば、プロセスA、Bがあり、Aのほうで定義(合っていますか?)した
static関数Aがあった場合、
プロセスBからstatic関数Aは呼べるのでしょうか?
もしくは、プロセスBで定義したstatic関数Bをstatic関数A内で
呼ぶことはできるのでしょうか?
よろしくおねがいします。

補足日時:2009/05/20 22:25
    • good
    • 0

> このとき、Main.exe内では、libraryをnewすることもなく、


> library::GetX();と呼べるわけですが、

staticじゃなきゃ呼べませんよ?

この回答への補足

ご指摘ありがとうございます。
staticでないと呼べないですね。

補足日時:2009/05/20 22:34
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!