簡體   English   中英

訪問子類C ++的屬性/功能

[英]Accessing Properties/Functions of Subclasses C++

我的程序中存在設計問題,因為我偶爾需要訪問子類的屬性和方法,這些屬性和方法都存儲在基類指針的向量中。 我的代碼如下所示:

class B1;
class B2;
class Base {
  private:
  int id, a, b;

  public:
  virtual int getA() { return a; }
  virtual int getB() { return b; }
  virtual B1 *getB1() { return NULL; } //seems like a bad idea
  virtual B2 *getB2() { return NULL; }  //to have these two functions
  Base(int newId) { id = newId; }
};

class B1 : public Base {
   private:
   int x;

   public:
   int getX() { return x; }
   B1 *getB1() { return this; }
};

class B2 : public Base {
   private:
   int y;

   public:
   int getY() { return y; }
   B2 *getB2() { return this; }
};

class Thing {
   private:
   std::vector<Base*> bases;

   void addBase(Base *base) { bases.push_back(base); }
   void doB1Stuff();
   void doB2Stuff();
   void setAandB(int ID, int newA, int newB); //set a and b of one of the elements in bases vector based upon the id given
};

問題是如果我需要在Thing中訪問x或y,如下所示:

void Thing::doB1Stuff() {
  for(std::vector<Base*>::iterator it = bases.begin(); it != bases.end(); ++it) {
    if (it->getB1()) {
      //do stuff with b1
    }
  }
}

上面的代碼應該可以工作,但是如果這是一個壞主意,因為在使用這樣的B1 / B2屬性之前,很容易忘記檢查指針是否為空:

void Thing::doB2Stuff() {
  for(std::vector<Base*>::iterator it = bases.begin(); it != bases.end(); ++it) {
    std::cout << it->getY(); //I believe this will crash the program if a NULL pointer is returned
  }
}

因此,我的問題是:什么是訪問子類屬性的好方法? 我當時在考慮在Thing中為B1和B2提供兩個單獨的向量,但這似乎也不是一個好主意,因為我需要能夠輕松設置a和b。 有什么想法嗎?

您擁有的一切都很好:只要您不將NULL存儲在指針的bases向量中,就無需對從迭代器返回的值進行空檢查。 不幸的是,指針向量是多態對象容器的唯一選擇。 您可以創建一個共享指針向量來簡化刪除操作,但是基本思想保持不變。

您可以檢查正在訪問的項目是否是您要查找的正確的子類類型,盡管要執行此操作,您需要包括運行時類型信息(rtti)。

然后,如果它是某種類型且不為null,則可以將其強制轉換為該類型並調用正確的函數。

您也可以使用動態 _cast,盡管要再次使用該功能,您需要再次使用rtti,它本質上與檢查自己然后進行靜態轉換相同。

沒錯,這不是解決問題的好方法,可以使用dynamic_cast來確定使用哪個對象的安全方法,但這對我來說是不好的代碼味道。

我要訪問子屬性的方法是創建一個虛擬函數,該函數返回您在Base類中想要的值。

例:

class Base {
  private:
  int id, a, b;

  public:
  virtual int getA() { return a; }
  virtual int getB() { return b; }
  virtual int getSubValue() = 0; // 
  Base(int newId) { id = newId; }
};

class B1 : public Base {
   private:
   int x;

   public:
   int getSubValue() { return x; }   
};

class B2 : public Base {
   private:
   int y;

   public:
   int getSubValue() { return y; }   
};

然后,您可以調用它-> getSubValue()來獲取您請求的子值。

這是我的觀點,有很多方法可以解決此問題,但這是我根據您所提供的信息所建議的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM