プラットフォームに依存しないC++コードで、オブジェクトがヒープ上に作成されないようにする方法を知っている人はいますか?つまり、クラス「Foo」の場合、ユーザーがこれを実行できないようにします。
Foo *ptr = new Foo;
そして、これを行うことだけを許可します。
Foo myfooObject;
誰かアイデアはありますか?
乾杯、
プラットフォームに依存しないC++コードで、オブジェクトがヒープ上に作成されないようにする方法を知っている人はいますか?つまり、クラス「Foo」の場合、ユーザーがこれを実行できないようにします。
Foo *ptr = new Foo;
そして、これを行うことだけを許可します。
Foo myfooObject;
誰かアイデアはありますか?
乾杯、
ニックの答えは良い出発点ですが、実際にはオーバーロードする必要があるため不完全です:
private:
void* operator new(size_t); // standard new
void* operator new(size_t, void*); // placement new
void* operator new[](size_t); // array new
void* operator new[](size_t, void*); // placement array new
(適切なコーディングの実践では、delete および delete[] 演算子もオーバーロードする必要があることをお勧めします。私はそうしたいと思いますが、これらの演算子は呼び出されないため、実際には必要ありません。)
Pauldooは、Foo からの継承は生き残るが、これは Foo での集約には耐えられないということも正しいです。これを防ぐために、テンプレートのメタプログラミング マジックを実行することもできますが、「悪意のあるユーザー」の影響を受けないわけではないため、おそらく複雑にする価値はありません。それがどのように使用されるべきかの文書化と、それが適切に使用されていることを確認するためのコードレビューは、〜100% の唯一の方法です。
Fooの新規をオーバーロードして、プライベートにすることができます。これは、Foo内からヒープ上にFooのインスタンスを作成しない限り、コンパイラがうめき声を上げることを意味します。このケースを捕らえるために、Fooの新しいメソッドを書くことができず、リンカーは未定義のシンボルについてうめき声を上げます。
class Foo {
private:
void* operator new(size_t size);
};
PS。はい、これは簡単に回避できることを私は知っています。私は本当にそれをお勧めしていません-それは悪い考えだと思います-私はただ質問に答えていました!;-)
私はそれを確実にそしてポータブルな方法で行う方法を知りません..しかし..
オブジェクトがスタック上にある場合、コンストラクター内で「this」の値が常にスタックポインターに近いことを表明できる場合があります。この場合、オブジェクトがスタック上にある可能性が高くなります。
すべてのプラットフォームが同じ方向にスタックを実装しているわけではないので、アプリがスタックの成長方向を確認し始めたときに1回限りのテストを実行することをお勧めします。
FooClass::FooClass() {
char dummy;
ptrdiff_t displacement = &dummy - reinterpret_cast<char*>(this);
if (displacement > 10000 || displacement < -10000) {
throw "Not on the stack - maybe..";
}
}
@ニック
これは、Fooから派生またはFooを集約するクラスを作成することで回避できます。私が提案することは(堅牢ではありませんが)、派生クラスと集約クラスでも機能すると思います。
例えば:
struct MyStruct {
Foo m_foo;
};
MyStruct* p = new MyStruct();
ここでは、Fooの非表示の新しい演算子をバイパスして、ヒープ上に「Foo」のインスタンスを作成しました。
デバッグ ヘッダーはオペレーターの新しい署名をオーバーライドできるため、完全な解決策として ... 署名を使用することをお勧めします。
private:
void* operator new(size_t, ...) = delete;
void* operator new[](size_t, ...) = delete;
Fooクラス内で「operatornew」と呼ばれる関数を宣言して、通常の形式のnewへのアクセスをブロックすることができます。
これはあなたが望む種類の行動ですか?
これをインターフェースとして宣言し、独自のコードからより直接的に実装クラスを制御することができます。
これがコンパイル時の機会を提供するかどうかはわかりませんが、クラスの「new」演算子のオーバーロードを検討しましたか?