簡體   English   中英

C ++在運行時確定多態對象的類型

[英]C++ Determine the type of a polymorphic object at runtime

我正在嘗試一個項目,該項目需要我在運行時確定多態對象的類型,以便可以進行轉換。 我的意思的例子:

class A{
};
class B: public A{
    public:
        void foo(){
            printf("B::foo()\n");
        }
};

稍后,我將有一堆本質上是這樣存儲的B對象:

std::vector<A*> v;
v.push_back(new B());

我將需要調用某些重載方法,這些方法定義為:

void bar(B* b){
    b->foo();
}

傳入存儲在v中的對象之后。 那我遇到的問題是,在我的實際使用情況,我不知道的類型, B在編譯時間,所以我不能只是呼吁barbar((B*)v.get(0));

我一直想我可能需要的解決方案是以某種方式確定每個對象在運行時的類型,以便可以在將其傳遞給bar之前進行強制轉換。

到目前為止,我嘗試過的解決方案是使用decltype ,但是它對我不起作用,因為它只返回傳入值的靜態類型,而不是運行時的類型。

另外,我不想為此項目使用第三方庫,因為我希望使其盡可能小。

謝謝您的幫助。

編輯:

我在描述問題時的意思還不夠清楚。 在我的實際用例中(嘗試在此處發布會有點長,盡管我可以在必要時發布其中的一部分),我試圖編寫一個庫,其中有一個基類(在此表示為A ),可以由用戶擴展到他們自己的自定義類(在此表示為B )。 在我的示例中, B::foo()僅用於表示A每個子類如何擁有自己的數據成員,這些數據成員稍后通過某種方法(在我的示例中表示為bar )進行處理。 這也是A無法簡單地使用某些虛擬foo方法的原因。

我遇到的主要問題是,由於B應該是用戶定義的,所以我不知道它在編譯時是什么,但是我在鏈接時就知道了(因為鏈接稍后出現)。 這就是為什么無法使用dynamic_cast (由Sam和Remy建議)的原因,因為據我了解,它要求我知道B可能是什么的所有可能性,而我不知道。 盡管它看上去確實很適合我。 如果有某種方法可以獲取所有可能的子類(例如,使用預處理器宏或模板),那么我認為這可能可以工作。

我希望這次我能更好地解釋它。 再次感謝你的幫助。

編輯2:另一個澄清點:在我正在從事的實際項目中,我只希望用戶被要求編寫自己的B類和重載bar以使用其自定義類。 但是,我不希望用戶要求調用bar 相反,我想從基類(我定義)中調用bar 這就是我什至嘗試這樣做的主要原因。 那,看看我是否可以。

希望這能清除一切。 再次感謝你。

這就是虛擬方法的目的。

A聲明foo()虛擬方法,您不必擔心進行丑陋的強制轉換。

或者,如果A至少具有一個虛函數-並且一個虛擬析構函數將做-您可以使用dynamic_cast<>嘗試運氣。

在C ++中,(動態) 多態性是用於此類事物的工具。

struct A {
  virtual void foo() = 0;
  virtual~A() {}
};

struct B : A {
  void foo() override;
};

std::vector<std::unique_ptr<A>> vA;
vA.emplace_back(new B);
vA[0]->foo();

無需查找vA[0]指向的對象的實際類型, virtual函數調用機制將找到正確的函數(在本例中為B::foo() )。 注意class Avirtual析構函數。 它保證(的派生的對象class B )被正確地從一個指針刪除,以A (如保持在由unique_ptr<A> )。

當然,還有dynamic_cast<> ,它允許您測試對象是否實際上是某種類型:

auto ptr = dynamic_cast<B*>(vA[0].get());
if(ptr)   // object is a B
  std::cout<<" have B";

我認為這對您有用。 首先,我們定義一個純虛擬成員函數call_bar以便我們可以在基類A上調用它。 對於實現,我們需要正確的類型,但是使用CRTP的用戶類可以為我們指定它。

class A
{
public:
  virtual void call_bar() = 0;
  virtual ~A() {}
};

template <typename T>
class B : public A
{
public:
  virtual void call_bar() override
  {
    bar(static_cast<T*>(this));
  }
};

class C: public B<C>
{
};

我一直想我可能需要的解決方案是以某種方式確定每個對象在運行時的類型,以便在將其傳遞給bar之前可以對其進行轉換。

您正在尋找dynamic_cast

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

class B: public A
{
public:
  void foo() {
    printf("B::foo()\n");
  }
};

...

std::vector<A*> v;
v.push_back(new B);

...

A *a = v.get(0);
B *b = dynamic_cast<B*>(a);
if (b)
    bar(b);

暫無
暫無

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

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