C++/CLI コンパイルエラー2127が解消できない

huahi11115 640 評価のポイント
2025-07-25T01:10:59.9333333+00:00

下記のコードで、virtual void Dispose() の行でコンパイルが通りません。

エラー2127.「この型のメンバー "Dispose"は、マネージドクラス内で予約されています。デストラクターを意識しましたか?」

対処方法が分かりません。

このエラーのため、virtual void Dispose(){}が使えず、void dispose0() というメソッドを作って~CL_pinPtr_Class()からコールしています。この状態では動作するので放置しても構わないのですが、

[インスタンス名]->Dispose()を使って明示的に開放を行いたいところが、仕方無く[インスタンス名]->dispose0(); という意味不明なコードになってしまうのを改善したいです。

public ref class CL_pinPtr_Class :IDisposable {
public:
	cl_mem Mem = 0;
	CL_aligned_malloc^ AMBuffer1 = nullptr;
	CL_pinPtr_Class00^ pt01;
	CL_pinPtr_Class(cl_context _context, CL_pinPtr_Class00^ pt0) {
		if (_context == 0) return;
		pt01 = pt0;
		AMBuffer1 = gcnew CL_aligned_malloc(_context, pt0->byteLength);
	}

	~CL_pinPtr_Class() {
		dispose0();//できれば、ここで Dispose(); とするのが理想
	}
	virtual void Dispose() {//コンパイルが通らない
		dispose0();
	}
	void dispose0() {
		if (AMBuffer1 != nullptr) {
			AMBuffer1->dispose0();//これも同様で、クラス内でDispose()がコンパイルエラーになり使えないのでdispose0()というメソッドで代用している
			AMBuffer1 = nullptr;
		}
		if (Mem != NULL) {
			int err = clReleaseMemObject(Mem);
			Mem = NULL;
		}
	}
};

開発者テクノロジ | .NET | その他
開発者テクノロジ | .NET | その他

.NET ソフトウェア フレームワークに基づく Microsoft テクノロジ。 特定のカテゴリに適合しないその他のトピック。

0 件のコメント コメントはありません

質問作成者が受け入れた回答
gekka 14,551 評価のポイント MVP ボランティア モデレーター
2025-07-25T09:23:42.4433333+00:00

デストラクターとファイナライザー

C++/CLIではIDisposableは暗黙的に実装されるので明示的な実装はできません。(C#/VBなどからはその暗黙的に実装されたDispose()を実行できる)

System.IDisposable インターフェイス

重要 .NET Framework では、C++ コンパイラはリソースの確定的な破棄をサポートしており、 Dispose メソッドを直接実装することはできません。

C++では言語の仕様として削除の機能がある兼ね合いで、このようになっているらしいです。

IDisposable インターフェイスで言語をC++にするとC++/CLIでの扱い方の説明があります。


表示が気に入らないだけなら#defineで偽装すればいいです

#define Dispose() dispose0()

public interface class IDispose0
{
	void dispose0() = 0;
};


public ref class CL_pinPtr_Class : public IDispose0  {
public:

	CL_pinPtr_Class(int v) : v(v)
	{
	}

	~CL_pinPtr_Class()  {
		//C#などのDispose()の呼び出しの場合は暗黙のDisposeからここが呼ばれる

		System::Diagnostics::Debug::WriteLine(L"~CL_pinPtr_Class デストラクタ {0}" ,this->v);
		
		dispose0();
	}

	!CL_pinPtr_Class()
	{
		System::Diagnostics::Debug::WriteLine(L"!CL_pinPtr_Class  マネージファイナライザ {0}",this->v);
		dispose0();
	}

	//ref classでは暗黙的にIDisposableが定義されるので再実装はできない
	//virtual void  Dispose() {
	//}


private:
	int v;
	bool isDisposed=false;

public:
	virtual void dispose0() {

		System::Diagnostics::Debug::WriteLine(L"\tDispose0");

		auto frames = (gcnew System::Diagnostics::StackTrace())->GetFrames();
		for each (auto frame in frames)
		{
			System::Diagnostics::Debug::WriteLine(L"\t\t{0}" , frame->GetMethod());
		}


		if (isDisposed)
		{
			return;
		}
		isDisposed = true;

	}
};

void Test(int testtype)
{
	CL_pinPtr_Class^ x = gcnew CL_pinPtr_Class(testtype);

	auto id = dynamic_cast<IDisposable^>(x);
	if (id != nullptr)
	{
		System::Diagnostics::Debug::WriteLine(L"IDisposableは実装されている");
	}

	switch (testtype)
	{
	case 1:
		System::Diagnostics::Debug::WriteLine(L"## delete");
		delete x;
		break;
	case 2:
		System::Diagnostics::Debug::WriteLine(L"## デストラクタ");
		x->~CL_pinPtr_Class();
		break;
	case 3:
	{
		System::Diagnostics::Debug::WriteLine(L"## リフレクションで強引にDispose");
		auto dispose = x->GetType()->GetMethod(L"Dispose");
		dispose->Invoke(x, nullptr);
		break;
	}
	default:
		System::Diagnostics::Debug::WriteLine(L"## 明示的な削除をしない場合");
		break;
	}

	x = nullptr;
}

int main(array<System::String^>^ args)
{
	{
		System::Diagnostics::Debug::WriteLine(L"## スコープから外れるときの自動削除の場合");
		CL_pinPtr_Class test(0);
	}

	{
		Test(1);
		Test(2);
		Test(3);
		Test(4);
	}


	{
		CL_pinPtr_Class^ y = gcnew CL_pinPtr_Class(5);
		y->Dispose(); //偽インターフェースと#defineを組み合わせた方法
	}
}

この回答は役に立ちましたか?

1 人がこの回答が役に立ったと思いました。

0 件の追加の回答

並べ替え方法: 最も役に立つ

お客様の回答

質問作成者は回答に "承認済み"、モデレーターは "推奨" とマークできます。これにより、ユーザーは作成者の問題が回答によって解決したことを把握できます。