3

次のコードを検討してください。

    #include <iostream>
    using namespace std;
    class superclass;
    class subclass;
    class subclass2;
    class superclass
    {
    public:
        unsigned int a;
        superclass **superman;

    };
    class subclass : public superclass
    {
    public:
        unsigned int b;
    };
    class subclass2 : public superclass
    {
    public:
        unsigned int b;
    };
    class runner
    {
    public:
        superclass **superman;
        runner()
        {
            *superman=new superclass[2];
            superman[0]=new subclass;
            superman[0]->a=3;
            superman[1]=new subclass2;
            superman[1]->a=4;
        }

    };
    int main() {

        runner r;
        cout<<r.superman[0]->a<<" "<<r.superman[1]->a;
        return 0;
    }

ご覧のとおり、親クラスへの参照の動的に割り当てられたストレージを作成したいのですが、それぞれが子クラスを指すことができますが、その配列から子クラスを再度抽出する方法がわからないため、その配列にアクセスできます変数 b;

次のアプローチを試しましたが、うまくいきませんでした。「'superclass*' から非スカラー型 'subclass' への変換が要求されました」および「'superclass*' から非スカラー型 'subclass2' への変換」というエラーが表示されます。要求された」

    subclass s1=r.superman[0];
    subclass2 s2=r.superman[1];

私は小さな何かが欠けていると確信しています。

PS: 同様の質問は見つかりませんでしたが、存在する場合はリダイレクトしてください。

4

3 に答える 3

2

この場合、本当にスマートポインターが必要であり、スーパークラスはそれ自体へのポインターを持っている必要はありません。ポリモーフィズムが引き続き機能するように、実際の派生クラスを指すスーパークラスポインターをベクトルに格納できます。

#include <memory>
#include <vector>

struct superclass
{
public:
  superclass() : a(0) {}
  virtual ~superclass() {}  // it's important to define virtual destructor as superclass is a base class
  int getA() const { return a; }

private:
  unsigned int a;
};

class subclass : public superclass
{
public:
    unsigned int b;
};
class subclass2 : public superclass
{
public:
    unsigned int b;
};

class runner
{
public:
  std::vector<std::unique_ptr<superclass>> superman;
  runner()
  {    
      superman.emplace_back(new subclass());
      superman.emplace_back(new subclass2());
  }    
};

次に、簡単にアクセスできます。

   int main() 
   {    
       runner r;
       std::cout << r.superman[0]->getA() <<" " < <r.superman[1]->getA();
       return 0;
   }

補足:可能であればデータを非表示にし、set / get関数を介してデータにアクセスし、メンバーをパブリックとして宣言しないでください。

于 2013-01-15T09:05:41.067 に答える
1
    superclass **superman;
    runner()
    {
        *superman=...

これらの数行のコードは、未定義の動作をコードに与えます。初期化されていないポインターを逆参照して、すべてが正常に機能することを期待することはできません。

于 2013-01-15T09:06:32.833 に答える
1

virtualデストラクタを追加しsuperclassて使用しますdynamic_cast

class superclass
{
public:
    unsigned int a;
    superclass **superman;
    virtual ~superclass(){}; // You must at least have one virtual method
                             // in your superclass and destructor is good choice 
                             // Otherwise, dynamic_cast wouldn't work:
                             // error: ... (source type is not polymorphic) !
};
// ...
// s1 and s2 must be pointers:
subclass  *s1=dynamic_cast<subclass* >(r.superman[0]);
subclass2 *s2=dynamic_cast<subclass2*>(r.superman[1]);
//...

注: 基本クラスから派生クラスへのキャストには注意してください。割り当てられたメモリを解放することを忘れないでください。

于 2013-01-15T09:44:59.043 に答える