簡體   English   中英

使用純虛函數的C ++繼承

[英]C++ Inheritance with pure virtual functions

我正在嘗試創建一個充當基礎對象的類,然后將其細分(=實現)以用於各種目的。

我想定義一個或多個純虛函數,因此無論如何都是基類​​的子類,並且不會忘記實現它們。

有一點需要注意,純虛函數的簽名包括基礎對象的類型。 一旦被分類,函數定義當然不再與基類定義匹配。 例如:

class BaseItem 
{
public:
    virtual std::string getDifferences(const BaseItem& item) = 0;
}

所以,在我想做的派生類中:

class DerivedClass : public BaseItem
{
public:
    virtual std::string getDifferences(const DerivedClass& item) = 0;
private:
    std::string derivedItemCustomObject;
}

當然編譯器不會接受。 我當然可以把它變成一個BaseItem ,但是我不能在派生類中使用任何對象。

我是否必須使用鑄造才能完成此任務?

如果我的意圖/問題不明確,請告訴我。

無需更改功能簽名 請看以下內容:

class BaseItem 
{public:
    virtual std::string getDifferences(const BaseItem& item) = 0;
};

class DerivedClass : public BaseItem
{public:
    virtual std::string getDifferences(const BaseItem& item)  // keep it as it's
    {
       const DerivedClass& derivedItem = static_cast<const DerivedClass&>(item);
    }
};

可以毫不畏懼地使用static_cast<> ,因為DerivedClass::getDifferences()僅針對DerivedClass對象調用。 為了顯示,

BaseItem *p = new DerivedClass;
DerivedClass obj;
p->getDifferences(obj);  // this always invoke DerivedClass::getDifferences

如果您擔心有時可能會將任何其他派生類對象作為參數傳遞給該方法,那么請使用dynamic_cast<>並在該轉換失敗時拋出異常。

目前還不清楚你想要實現的目標。 假設編譯器允許您執行此操作(或者通過強制轉換方式執行此操作),那么它將在類型系統中打開以下漏洞:

class BaseItem 
{
public:
    virtual std::string getDifferences(const BaseItem& item) = 0;
};

class DerivedClass : public BaseItem
{
public:
    virtual std::string getDifferences(const DerivedClass& item) 
    {
        item.f(); 
        // ... 
    }

    void f() const {}
};

class DerivedClass2 : public BaseItem
{
public:
    virtual std::string getDifferences(const DerivedClass2& item) { ... }
};

void g()
{
    BaseItem* x = new DerivedClass;

    // oops, calls DerivedClass::f on an instance of DerivedClass2
    x->getDifferences(DerivedClass2());
}

你的設計可能是錯的。

我假設編譯器接受但DerivedClass :: getDifferences不會覆蓋BaseItem :: getDifferences。 這是一種實現您顯然想要的方法

template <typename T>
class DerivedHelper: public BaseItem {
public:
   virtual std::string getDifferences(const BaseItem& item) {
      getDifferences(dynamic_cast<const T&>(item));
   }
   virtual std::string getDifferences(const T& item) = 0;
}; 

class DerivedClass : public DerivedHelper<DerivedClass>
{
public:
   // not more needed but providing it will hide getDifferences(const BaseItem& item)
   // helping to statically catch some cases where a bad argument type is used.
   virtual std::string getDifferences(const DerivedClass& item) = 0;
private:
   std::string derivedItemCustomObject;
};

但要注意有一個運行時檢查,如果參數不是正確的類,它將拋出異常。

實現此目的的一種方法是使用模板並使參數成為派生類型的類型

template <typename T>
class BaseItem {
public:
  virtual std::string getDifferences(const T& item) = 0;
};

class DerivedClass : public BaseItem<DerivedClass> {
public:
  virtual std::string getDifferences(const DerivedClass& item) {
    // Implement it here
  }
};

如果給定的BaseItem是DerivedClass實例,則應該使用從BaseItem轉換為DerivedClass +運行時檢查。

暫無
暫無

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

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