質問者
データのサブクラス化

質問
-
.NET2005 VISTA です。
CLRでデータの安全性を保つ方法について質問します。
MFCですと、よくデータをサブクラス化すると思うのです。
***view.cpp で
class hoge a[5];
***.h で
class hoge {
private:
char data;
public:
void setdata(CString ss);
CString getdate();
};
extern class hoge a[5];とするようなやり方です。
CLRの場合は、どのようにコードィングしたらいいのでしょうか。
過去ログを見ると、グローバル変数の作り方として、
global というサブクラスを作っておいて、
Code Snippet// global.h
#ifndef GLOBAL_H__
#define GLOBAL_H__
ref class Global {
public:
static array^ ss;
private:
static Global();
};
#endifCode Snippet// global.cpp
#include "stdafx.h"
#include "global.h"static Global::Global() {
ss = gcnew array<System::String^,2>{ {"0-0","0-1"}, {"1-0","1-1"}, };
}というのがありますが、
サブクラスに置いても、これはスレッドの趣旨どおり外部変数だと思うのです。
要は、private にするかどうか、ということかとも思ったのですが、その場合にデータの出し入れをどうするかということも分りません。
CLRでは、データの安全性を保つ場合、一般的に、どのようにするのでしょうか。
すべての返信
-
#あまりサブクラス化とは言わないような……
一般的には、プロパティかメソッドでカプセル化します。
フィールド(つまりメンバ変数)は private にして、これらは public にします。
問題は、プロパティとメソッドのどちらを使用すべきかと云う点ですが、
これについては下記ページにガイドラインがありますので、参考にしてください。
http://msdn2.microsoft.com/ja-jp/library/ms229054(VS.80).aspx
-
-
Abstract さん、ありがとうございます。
> 一般的には、プロパティかメソッドでカプセル化します。
> フィールド(つまりメンバ変数)は private にして、これらは public にします。
正直なところ、この部分からよくわかりません。
メンバ変数を置く場所は、Form1.h の中なのでしょうか。
たとえば、二次元配列 static array<System:
tring^,2>^ ss を private にするとして、
データの出し入れは、どのようにするのでしょうか。
public なら、
ss = gcnew array<String^, 2>(2, 4){
{・・・・というように素直に定義していけばいいと思うのですが。
心苦しいのですが、コードを示して頂けませんでしょうか。
-
外池と申します。
すいません、議論がすれ違いにならないか、老婆心ながら懸念しています。すれ違いにならないように、変に誤解している(誤解をまねく)用語を用いずに(サブクラスとか、カプセルとか)、平易にやりたいことを説明してください。
1.Windowsアプリだと思いますが、それでよろしいですか?
2.安全な場所に隠しておきたい2次元配列は、
Formオブジェクトの個々のインスタンスごとに用意すべきものですか?
それともFormクラスに属するものの、複数のインスタンスから共通にアクセスできることを意図していますか?
それともFormクラスとは無関係に、プログラムのどこからでも共通にアクセスできることを意図していますか?
3.その上で、改めて、上述の2次元配列は、何からのアクセスに対して、安全に隠しておきたいのですか?
これらの説明がなされていない、つまり、ご質問の背景にある意図が不明なので(誤った用語を用いたら、一層混乱する)、どなたも返答に窮することになろうかと思います。
-
Global.h
public ref class Global
{
private:
static array<String^,2>^ ss;
private:
static Global(void);
public:
static array<String^,2>^ GetSS(void);
};Global.cppstatic Global::Global(void)
{
ss = gcnew array<String^,2>{{"0-0","0-1"},{"1-0","1-1"}};
}array<String^,2>^ Global::GetSS(void)
{
return ss;
}とか。
注:実際には ss をそのまま返すのでなく、複製したものを返すほうが安全です。
-
ありがとうございます。
ご提示のコードのままで通らなかったので、下記のようにしました。
global.cpp#include "stdafx.h"
#include "global.h"using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;static Global::Global(void)
{
ss = gcnew array{{"0-0","0-1"},{"1-0","1-1"}};
}array^ Global::GetSS(void)
{
return ss;
}global.h#pragma once
namespace dataclass {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;public ref class Global
{
private:
static array^ ss;
private:
static Global(void);
public:
static array^ GetSS(void);
};
}これで、まだ、
'Global' : 識別子がクラス名でも名前空間名でもありません。
型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
'ss' : 定義されていない識別子です。
'Global' : 関数に戻り値の型が指定されていません。戻り値を void 型と見なします。
'Global' : 識別子がクラス名でも名前空間名でもありません。というエラーになります。
やっていて、いくつか疑問が出たのですが、
1.これが、「プロパティまたはメソッドでカプセル化」なのでしょうか。
2.Form1.hで、配列の値を取得するには、どのようなコードになるのでしょうか。
3.逆に、private な ss の値を上書きする関数は、どのようなコードになるのでしょうか。
4.MFCですと、なにをするにもまずサブクラス化してから、みたいなところがありますが、
そもそもCLRでは、あまりサブクラスは使わないのでしょうか。
アドバイスを、よろしくお願いいたします。
-
2点のみ回答します。
初々心者 さんからの引用 'Global' : 識別子がクラス名でも名前空間名でもありません。
型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
'ss' : 定義されていない識別子です。
'Global' : 関数に戻り値の型が指定されていません。戻り値を void 型と見なします。
'Global' : 識別子がクラス名でも名前空間名でもありません。というエラーになります。
global.hでは”namespace dataclass { ”の行がありますがglobal.cppにはありません。
global.cppに”namespace dataclass { ”を追加してみてください。
(最終行に } を追加するのも忘れずに)
初々心者 さんからの引用 4.MFCですと、なにをするにもまずサブクラス化してから、みたいなところがありますが、
そもそもCLRでは、あまりサブクラスは使わないのでしょうか。
他の方もすでに書かれていますが、初々心者さんは「サブクラス化」という用語を間違って使っています。
【サブクラス化】
http://e-words.jp/w/E382B5E38396E382AFE383A9E382B9E58C96.html
MFCでサブクラス化を行う場合は例えばCButtonクラスを継承して機能追加したボタンクラスを作るなど
そういった場合に「サブクラス化」すると言います。
今回の場合は単純にクラスの作り方についての質問かと思います。
-
Global の完全限定名(つまり本名)が dataclass::Global になっているのでエラーになります。
だから解決策は、.cpp の方に using namespace dataclass; を追加するか、
或いは .h の方で namespace dataclass{} を削除するか。追記:C.John さんの提示された方法も有効です。
基本的に、外部の名前空間の中で宣言されている型は、
その型名の前に名前空間名を付けないとアクセスできません。
だから String だって、System:: String^ としなければ、
「String はクラスでも名前空間でもない」となるわけです。
この事は重要ですので、是非覚えてください。あと疑問についての回答。
1、
そうですね。「隠蔽する」とも言いますが。2、
Form1.h がどんなんであるか、私は知りませんが、
Global::GetSS();
これだけ。3、
static void SetSS(array<String^,2>^ value)
{
ss = value;
}
みたいな(未検証)。4、
Win32 や MFC でのサブクラス化は、
CLR においては WndProc をオーバーライドする事を意味します。
あまり一般的ではありません。 -
-
-