VB 使いが C++ で違和感を感じるもののひとつが static かも知れないな。たとえば関数スコープの変数を、static/Staticで加算していくこんなクラス
' VB ' CIncriment Option Explicit Public Function Incriment() As Long Static slngNumber As Long slngNumber = slngNumber + 1 Incriment = slngNumber End Function
// C++ // CIncriment class CIncriment { public: int Incriment () { static int siNumber = 0; return ++siNumber; } };
これで、だいたい一緒かな?これを、インスタンスを作成しては、Incriment メソッドをコールしてみる。
まず VB 。フォームモジュールにコマンドボタンを一個。
メンバへのポインタ演算子ってやつがある。MSDNライブラリでの説明はこう。
メンバへのポインタ演算子:.*および->*
pm-expression:cast-expressionpm-expression.*cast-expressionpm-expression->*cast-expression二項演算子
.*は第 1 オペランドを第 2 オペランドに結合します。第 1 オペランドはクラス型のオブジェクトとし、第 2 オペランドはメンバへのポインタ型とする必要があります。二項演算子
->*も第 1 オペランドを第 2 オペランドに結合します。この第 1 オペランドはクラス型のオブジェクトを指すポインタ、第 2 オペランドはメンバへのポインタ型にする必要があります。演算子
.*を使った式の第 1 オペランドの型は、第 2 オペランドで指定した、メンバへのポインタと同じクラス型にするか、そのクラスから明確に継承させたあいまいさのない型にする必要があります。演算子
->*を使った式の第 1 オペランドの型は、第 2 オペランドで指定した型の "クラス型へのポインタ" にするか、そのクラスから明確に継承させたあいまいさのない型にする必要があります。
この説明で、は、はーん、ってわかった人いますかね。私はわかりませんでした。
この演算子が何なのか、何でこんなものいるか、というと、まず、クラスのメンバ関数を、関数ポインタからコールしたい、という場合があるとします。クラスのメンバ関数も関数なので、もちろん関数ポインタをとることができます。たとえばこんな感じ。
Oracle の表と列にコメントをつけることができます
SQL> comment on table MY_TABLE is '私のテーブル'; コメントが作成されました。 SQL> comment on column MY_TABLE.MY_COLUMN is '私のカラム'; コメントが作成されました。
こうして付けたコメントは USER_TAB_COMMENTS と USER_COL_COMMENTS というデータディクショナリで参照することができます。こんな感じのテーブルになってます。
SQL> desc USER_TAB_COMMENTS 名前 NULL? 型 ----------------------------------------- -------- ---------------------------- TABLE_NAME NOT NULL VARCHAR2(30) TABLE_TYPE VARCHAR2(11) COMMENTS VARCHAR2(4000) SQL> desc USER_COL_COMMENTS 名前 NULL? 型 ----------------------------------------- -------- ---------------------------- TABLE_NAME NOT NULL VARCHAR2(30) COLUMN_NAME NOT NULL VARCHAR2(30) COMMENTS VARCHAR2(4000)
仕事で、ローカルコンピュータ名を取得する必要がありそうなのですが、WinSock で取得しても面白くないので、今回は NetServerGetInfo で、VB 用の関数を作ってみました。ただし、Windows Me、98、95 等では関数定義が異なるため、使用できません。
DLLよりコールした GetModuleFileName で取得されるパスにもコメントをいただいたのですが、DLL 内で GetModuleFileName を、1つ目の引数 hModule に NULL を指定して呼び出すと、その DLL をロードしたプロセスの実行ファイルのパスが取得されてしまいます。ほんで結局、DLL 側で、自分自身のパスを知る方法はないの?って話です。
コメントをいただいたときは、「MFC の DLL なら、theApp.m_pszHelpFilePath の拡張子を"exe"に替えれば・・・」と、とぼけた答えを返してしまったのですが、ふと思いついて、DllMain の宣言を見ると、引数に HANDLE hModuleというのがあるではありませんか。それを渡して GetModuleFileName してみました。
BOOL APIENTRY DllMain (HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
TCHAR szModuleFileName [_MAX_PATH] = _T ("");
GetModuleFileName ((HMODULE) hModule, szModuleFileName, _MAX_PATH);
MessageBox (NULL, szModuleFileName, _T ("ModuleFileName"), MB_OK);
return TRUE;
}
結果はきちんと、DLL 自身のパスが表示されました。あとで、MSDN ライブラリの DllMain をみると、ちゃんと書いてありました。
DLL モジュールのハンドルを指定します。この値は、DLL のベースアドレスです。DLL の HINSTANCE は、DLL の HMODULE と同じことを意味します。(これらは混同されていることがあります。詳細については Knowledge Base の Q81496 の「Dealing with hModule and hInstance」を参照してください。MSDN ライブラリの[検索]タブでも Q81496 を参照できます。)。したがって、モジュールハンドルを必要とする GetModuleFileName 関数などを呼び出す際に、hinstDLL パラメータで指定した値を使うことができます。
ちゃんと読めよ、ということかしら・・・
今日、こんな古いソースの中にこんな関数定義を見かけました。
int func (foo, bar) unsigned char *foo, *bar; { /* 処理・・・ */ ・・・
注目すべきは引数の宣言部分なのですが、調べてみると「伝統形式」と呼ばれるものらしいです。
ANSI C標準以前の宣言方法を伝統形式や旧方式というように呼ばれています
この方式による宣言は現代のコンパイラでも可能です
さらに、過去のC言語のソースで伝統形式が使われているものを見かけることがあるかもしれません
ここで、伝統形式の仮引数宣言を覚えておきましょう
(中略)
大きく違うのは、引数リストで仮引数となる変数名しか宣言しないということです
その後、コードブロックに入る前にそれぞれの仮引数に型を宣言するという形になっています