0

さまざまな種類のデータを配列またはベクトルに格納しようとしています。これまでのところ、各オブジェクトへのポインターとしてベクターに格納される基本クラスを使用してこれを行ってから、キャストと入力してデータを取得します。これはintには最適ですが、他のタイプのデータはアクセス違反の例外をスローします。

私の説明があまり良くない場合は申し訳ありませんが、ここに私が役立つことを願っているコメント付きの私のコードがあります:

//Base class
class MenuProperty
{
private:
    std::string Name;

public:
    MenuProperty(std::string Name) : Name(Name) {};
    ~MenuProperty() {};

    std::string GetName();

};

//Typed class used to store data
template<class T>
class TMenuProperty : public MenuProperty
{
private:
    T Data;

public:
    TMenuProperty(std::string Name, T Data) : MenuProperty(Name), Data(Data) {};

    T GetData()
    {
       return this->Data;
    }
};

//Class with no type and data pointer to retrieve data
class cpMenuProperty : public MenuProperty
{
private:
    VOID* Data;

public:
    cpMenuProperty(std::string Name) : MenuProperty(Name) {};

    VOID* GetPointer()
    {
       return this->Data;
    }
};

それが理にかなっていることを願って、ここに私のテストコードがあります:

int main()
{
    TMenuProperty<double> fP("Test2", 33.7354); //Create instance of property

    MenuProperty* fMP = &fP;                    //Make a pointer to the object

    cpMenuProperty* Test;                       //Make a pointer to the retrieving
                                                //object

    std::vector<MenuProperty*>              Vec;
    std::vector<MenuProperty*>::iterator    it;

    Vec.push_back(fMP);                         

    it = Vec.begin();

    Test = static_cast<cpMenuProperty*>(*it);   //Cast the first object in the list 
                                                //list to the same type as the
                                                //retrieveing object


    double Data = *(double*)Test->GetPointer(); //Dereference and access, this is
                                                //where the exception is thrown

    std::cout << Data;



    int Ret;
    std::cin >> Ret;
}

私はおそらくここでいくつかの記念碑的な誤りを犯していますが、これまで読んでくれてありがとう:)どんな助けもありがたいです、そして建設的な批判もあります!

4

2 に答える 2

2

スタック上のTMenuPropertyオブジェクトを初期化し、それをcpMenuPropertyにキャストします。cpMenuPropertyのvoid*データにメモリが割り当てられることはありません。TMenuPropertyとcpMenuPropertyの間には、同じクラスから派生していることを除いて、関係はありません。このデザインは決して機能しません。

  • すべてのvoid*を取り除きます。それはトラブルを求めています。
  • 自分が何をしているかを100%理解していない限り、static_cast<>を使用しないでください。dynamic_castを使用すると、変換が無効であることが通知されます(これを試したと思いますが、static_castにフォールバックして、コードを少なくともコンパイルするように強制します:))
  • TMenuPropertyをずっと使ってみませんか?そのアプローチはうまくいくはずです。
  • あなたが求めていることを行う他の方法については、boost::variantとboost::anyを見てください。
  • 勇気があり、自分が何をしているのかを本当に理解している場合(不快感はありませんが、これに該当するとは思いません)、ラップする必要のあるデータ型がメモリレイアウトに関して十分に均一である場合は、コードを適切なメモリパディング設定で機能させ、特定の方法でメモリアライメントを強制します。しかし、そのような理由を見つけるために、どんなにありそうもないシナリオ思いつくことはできません。したがって、この投稿からわかることから、cpMenuPropertyを削除し、抽象基本クラス/テンプレート化された派生クラスのアプローチのみを使用するようにアドバイスすることしかできません。
于 2012-12-31T14:50:55.657 に答える
0
 #include<iostream>
 #include<vector>
 #include<iterator>
 #include<memory>
 class base {
 public:
 virtual void foo(){
      std::cout << "in base" << std::endl;
  }
 };

 class derived : public base {
 public:
 virtual void foo(){
      std::cout << "in derived" << std::endl;
   }
 };

 int main()
 {
    std::vector<std::unique_ptr<base>> vec;
    vec.emplace_back(new derived);
    static_cast<derived*>(vec[0].get())->foo();
    return 0;
  }

古典的な例、現代の慣行を使用。

于 2012-12-31T14:45:32.913 に答える