簡體   English   中英

C ++將未知類型傳遞給虛函數

[英]C++ passing unknown type to a virtual function

我正在用C ++編寫,我想將未知類型(僅在運行時已知)傳遞給純虛函數:

virtual void DoSomething(??? data);

其中DoSomething是派生類中純虛擬功能的實現。

我打算使用模板,但事實證明,虛函數和模板不能一起使用: C ++類成員函數模板可以是虛擬的嗎?

我想避免對傳遞給函數的所有類使用基類(類似於C#中的對象 )。

提前致謝

您需要類型擦除 一個例子就是通用的boost::any (在C ++ 17中是std::any )。

virtual void DoSomething(boost::any const& data);

然后,每個子類都可以嘗試安全的 any_cast以獲得所需的數據。

void DoSomething(boost::any const& data) {
  auto p = any_cast<std::string>(&data);

  if(p) {
    // do something with the string pointer we extracted
  }
}

如果您尋求的行為范圍受到更多限制,那么您當然可以推出自己的擦除類型的抽象。

如果您不想使用boost / C ++ 17,請考慮從基類派生'doSometing'函數的參數,並動態轉換為正確的類對象。 在這種情況下,您可以在運行時檢查是否獲得了有效的指針。

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

template <typename T>
struct specificParam:param{
    specificParam(T p):param(p){}
    T param;
};


class Foo
{
public:
    virtual void doSomething(param* data) = 0;
};

template <typename T>
class Bar : public Foo
{
public:
    virtual void doSomething(param* data){
        specificParam<T> *p = dynamic_cast<specificParam<T> *>(data);

        if (p != nullptr){
            std::cout<<"Bar got:" << p->param << "\n";
        }
        else {
            std::cout<<"Bar: parameter type error.\n";
        }
    }
};

int main(){
  Bar<char>   obj1;
  Bar<int>    obj2;
  Bar<float>  obj3;

  specificParam<char>   t1('a');
  specificParam<int>    t2(1);
  specificParam<float>  t3(2.2);

  obj1.doSomething(&t1); //Bar got:a
  obj2.doSomething(&t2); //Bar got:1
  obj3.doSomething(&t3); //Bar got:2.2

  // trying to access int object with float parameter
  obj2.doSomething(&t3); //Bar: parameter type error.
}

最簡單(但不安全!)的方法是使用void *指針+靜態強制轉換

class Foo
{
public:
    virtual void doSomething(void* data) = 0;
};

template <typename T>
class Bar:public Foo
{
public:
    virtual void doSomething(void* data){
        T* pData = static_cast<T*>(data);
        std::cout<<"Bar1 got:" << *pData << "\n";
    }
};

int main(){

  Bar<char>  obj1;
  Bar<int>   obj2;
  Bar<float> obj3;

  char  c = 'a';
  int   i = 1;
  float f = 2.2;

  obj1.doSomething(&c); // Bar1 got:a
  obj2.doSomething(&i); // Bar1 got:1
  obj3.doSomething(&f); // Bar1 got:2.2

  //obj2.doSomething(&c); // Very bad!!!     
}

類型擦除不是唯一的可能性。

您可能有興趣使用visitor模式:以std :: variant作為參數,並使用包含要實現的模板代碼的lambda進行訪問:

virtual void doSomething(std::variant<int,float/*,...*/> data)
   {
   visit([=](auto v){/*...*/;},data);
   }

是這樣的:

class Foo
{
    virtual ~Foo() = 0;
};

template <typename T>
class Bar : public Foo
{
    T object;
}

...

virtual void DoSomething(Foo* data)
{
    Bar<int>* temp = dynamic_cast<Bar<int>*>(data);
    if (temp)
         std::count<<temp->object;
}

暫無
暫無

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

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