簡體   English   中英

抽象類和唯一指針

[英]Abstract class and unique pointer

我的代碼中出現以下錯誤:

error: allocating an object of abstract class type 'Material'

我不知道如何處理這個案子。

我知道std::make_unique執行分配,所以它不能分配Material類型的對象,但我不知道如何糾正它。

#include <iostream>
#include <memory>

struct Material
{
  Material() = default;
  virtual int get_color() const = 0;
};

struct Basic : public Material
{
  Basic() = default;
  virtual int get_color() const override
  {
    return 1;
  }
};

struct Mix : public Material
{
  Mix(const Material& mat1, const Material& mat2)
    : mat1_(std::make_unique<Material>(mat1))
    , mat2_(std::make_unique<Material>(mat2))
  {}

  virtual int get_color() const override
  {
    return mat1_->get_color() + mat2_->get_color();
  }     
private:
  std::unique_ptr<Material> mat1_;
  std::unique_ptr<Material> mat2_;
};

int main()
{
  auto mix = Mix(Basic(), Basic());
  std::cout << mix.get_color() << '\n';
}

這個電話:

std::make_unique<Material>(mat1)

嘗試創建類Material的實例,它與mat1類型無關。 您似乎需要在您的類中使用方法clone()

class Material {
...
    virtual std::unique_ptr<Material> clone() const = 0;
};

Mix ctor將是:

Mix(const Material& mat1, const Material& mat2)
    : mat1_(mat1.clone())
    , mat2_(mat2.clone())
  {}

並且您需要在每個派生類中實現clone()

struct Basic : public Material
{
  Basic() = default;

  virtual std::unique_ptr<Material> clone() const override
  {
      return std::make_unique<Basic>( *this ); 
  }

  virtual int get_color() const override
  {
    return 1;
  }
};

問題是因為Mix嘗試創建抽象類Material的對象:

: mat1_(std::make_unique<Material>(mat1))

理想情況下,基於簽名

Mix(const Material& mat1, const Material& mat2)

Mix應該只能對傳遞給它的任何類型的Material進行操作。

使用抽象類引用傳遞Mix的事實很好。 但是, Mix試圖創建派生類的對象這一事實並不常見。 如果有其他派生類怎么辦?

我的設計略有不同,因此Mix 不是選民的所有者; 它們是由外面的東西創造和擁有的, Mix只是混合傳遞給它的東西。

struct Mix : public Material
{
  Mix(const Material& mat1, const Material& mat2)
    : mat1_{mat1}, mat2_{mat2}
  {}

  virtual int get_color() const override
  {
    return mat1_.get_color() + mat2_.get_color();
  }     
private:
  Material const& mat1_;
  Material const& mat2_;
};

int main()
{
  std::unique_ptr<Material> mat1 = std::make_unique<Basic>();
  std::unique_ptr<Material> mat2 = std::make_unique<Basic>();

  auto mix = Mix(*(mat1.get()), *(mat2.get()));
  std::cout << mix.get_color() << '\n';
}

您可以使用模板化構造函數來安排構造正確的類型,而無需克隆方法:

#include <iostream>
#include <memory>

struct Material {
    Material() = default;
    virtual int get_color() const = 0;
};

struct Basic : Material {
    Basic() = default;
    int get_color() const override {
        return 1;
    }
};

struct Mix : Material {
    template<typename M1, typename M2>
    Mix(const M1& mat1, const M2& mat2)
        : mat1_{std::make_unique<M1>(std::move(mat1))}
        , mat2_{std::make_unique<M2>(std::move(mat2))}
    {} 

    int get_color() const override {
        return mat1_->get_color() + mat2_->get_color();
    }

private:
    std::unique_ptr<Material> mat1_;
    std::unique_ptr<Material> mat2_;
};

int main() {
    auto mix = Mix(Basic(), Basic());
    std::cout << mix.get_color() << '\n';
}

請注意,僅當您發送具有已知類型的材質的實例時,此方法才有效。

http://www.cplusplus.com/forum/beginner/236974/包含正確的解決方案。 make_shared應該是特定類型; 然后你可以毫無問題地將它存儲在抽象類型的unique_ptr中。

暫無
暫無

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

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