0

これは危険なコードだと確信しています。しかし、正確に何がうまくいかないのかを誰かが知っているかどうかを確認したかった.

次のクラス構造があるとします。

class A {
protected:
  int a;
public:
  A() { a = 0; }        
  int getA() { return a; }
  void setA(int v) { a = v; }
};

class B: public A {
protected:
  int b;
public:
  B() { b = 0; }
};

そして、次のようにクラスを自動的に拡張する方法が必要だとします。

class Base {
public:
   virtual ~Base() {}
};

template <typename T>
class Test: public T, public Base {};

私ができる本当に重要な保証の 1 つは、他のメンバー変数やメソッドを持たBaseないことです。Testそれらは本質的に空のクラスです。

(潜在的に) 危険なコードは次のとおりです。

int main() {
  B *b = new B();

  // dangerous part?
  // forcing Test<B> to point to to an address of type B
  Test<B> *test = static_cast<Test<B> *>(b);

  //
  A *a = dynamic_cast<A *>(test);
  a->setA(10);
  std::cout << "result: " << a->getA() << std::endl;
}

このようなことを行う理由は、私が Test に似たクラスを使用していることですが、現在それを機能させるには、渡されたインスタンスをコピーするとともに、新しいインスタンス T (つまり Test) を作成する必要があります。Test を T のメモリ アドレスに向けることができれば、非常に便利です。

Base が仮想デストラクタを追加せず、Test によって何も追加されない場合、このコードは実際には問題ないと思います。しかし、仮想デストラクタを追加すると、型情報がクラスに追加されるのではないかと心配になります。その場合、メモリ アクセス違反が発生する可能性があります。

最後に、このコードは私のコンピューター/コンパイラー (clang) で正常に動作すると言えますが、これはもちろん、メモリに悪いことをしていないこと、および/または別のコンパイラー/マシンで完全に失敗しないことを保証するものではありません。

4

3 に答える 3

-1

操作を実行せず、Test<B>*スマート ポインターや自動メモリ管理などの魔法を回避する限り、問題はありません。

オブジェクトを検査するデバッグ プリントやロギングなどの隠蔽されたコードを必ず探す必要があります。このように設定されたポインターの値を調べようとしたために、デバッガーがクラッシュしました。これはあなたにいくらかの苦痛を与えるに違いありませんが、あなたはそれを機能させることができるはずです.

一番の問題はメンテナンスだと思います。一部の開発者が操作を行うまでにどのくらいかかりTest<B>*ますか?

于 2012-12-10T23:07:15.053 に答える