2013-11-26 23 views
0

什麼是派生演員用法的真正可以接受的例子?我一直認爲他們只是用於實施「黑客」,但如果情況並非如此,有人可以給出一個可以接受的例子,說明何時使用它?何時使用dynamic_cast的可接受示例?

+1

你是什麼意思「可接受」?誰可以接受? – Slava

+2

我想當你有一個指向'A'的指針,並且你不知道(或者你必須詢問宇宙來找出),如果它是'B'或'C'的話。在這種情況下,它會更容易使用dynamic_cast – Raxvan

+1

你知道,現實生活比書中描述的複雜得多。考慮例如當你剛剛開始一項新工作,需要處理新管理員編寫的遺留代碼時:),它不會實現雙重調度,因此您需要使用'dynamic_cast'。而且你很害羞,所以你絕對不想通過重寫這段代碼來開始你的工作。像這樣的東西。 –

回答

1

@ user997112

[在底部編輯]

你好。下面我們使用通過公共接口共同祖先
的隨機多態指針集合。
更多的工作與特定的派生類
我們需要的dynamic_cast或者typeid的知道這一點的一個做....
主要功能有通話
然後類聲明
那麼動態轉換是在結束
新創建的對象的刪除沒有顯示

#include <iostream> 
#include <algorithm> 
#include <random> 
#include <exception> 
using namespace std; 

int dynamic_test(); 
int main() 
{ 
    cout << "Hello world!" << endl; 
    dynamic_test(); 
    return 0; 
} 

............

class basex { 
    public: 
    virtual ~basex() {}; 
    virtual void work() const = 0; 
}; 
class next1x : public basex { 
    public: 
    void work() const override {cout << "1";/*secret*/} 
}; 
class next2x : public basex { 
    public: 
    void work() const override {cout << "2";/*secret*/} 
}; 
class next3x : public basex { 
    public: 
    void work() const override {cout << "3";/*secret*/} 
}; 

std::vector<basex *> secret_class_picker() 
{ 
    //pick classes with common base at random 
    std::random_device rd; 
    std::uniform_int_distribution<int> ud(1,3); 
    std::mt19937 mt(rd()); 
    std::vector<int> random_v; 
    for (int i = 0; i < 22; ++i) 
     random_v.push_back(ud(mt)); 
    cout << "Random" << endl; 
    for (auto bq : random_v) //inspecting for human reader 
     cout << bq << " "; 
    std::vector<basex *> v; 
    basex * bptr; 
    for (auto bq : random_v) { 
      switch(bq) 
      { 

      default: throw std::exception(); break; 
      case 1: bptr = new next1x; break; 
      case 2: bptr = new next2x; break; 
      case 3: bptr = new next3x; break; 
      } 

      v.push_back(bptr); 
    } 
    cout << "Objects Created " << v.size() << endl; 
    return v; 

} 

//this function demands a more derived class 
int special_work(const next3x *) 
{ 
    //elided 
    cout <<"[!]"; 
    return 0; 
} 

int dynamic_test() 
{ 
    std::vector<basex *> v = secret_class_picker();//delete these pointer later 
    cout <<"Working with random polymorphic pointers"<<endl; 
    for (const auto bq : v) 
    { 
     bq->work();//polymorphic 
     next3x * ptr = dynamic_cast<next3x *>(bq); 
     if (nullptr != ptr) special_work(ptr); //reserved for particular type 
    } 
    return 0; 
} 

......................替代

int dynamic_static_typeid() 
{ 
    std::vector<basex *> v = secret_class_picker(); 
    cout <<"Working with random polymorphic pointers"<<endl; 
    int k(0); 
    for (const auto bq : v) 
    { 
     bool flipflop = (k % 2) == 0; 
     bq->work();//polymorphic 
     //cout << "[*]"<< typeid(*bq).name();//dereference 

     if (flipflop) { 
      next3x * dc_ptr = dynamic_cast<next3x *>(bq);//not constant time in general 
      if (nullptr != dc_ptr) { 
       special_work(dc_ptr); //reserved for particular type 
       ++k; 
      } 
     } 
     else { 
      if (typeid(next3x) == typeid(*bq)){//constant time 
       auto sc_ptr = static_cast<next3x *>(bq);//constant time 
       special_work(sc_ptr); 
       ++k; cout <<"[sc]"; 
      } 
     } 
     cout << endl; 
    } 
    return 0; 
} 
+0

執行此操作的正常方法是將'special_work'虛擬爲一個空基類實現。 –

+0

@MarkB感謝您加強解釋。不同的選項總是很好。如果允許更改界面,這當然是一種選擇。有時候會有這方面的技術和社會障礙。在我的童話故事中,這只是一個不同的選擇。流運算符與此稍有關係。我們不是在談論命名空間標準問題,但有時候有一些特殊需要改變界面的理由有很多,或許不是廣泛的一般用法。 –

+0

好的,在這個例子中你基本上說你有一個很多子類型的向量,但如果你有next3x的子類型,你只想調用special_work()? – user997112

相關問題