[英]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.