我創建了一個Foo只需要用作共享指標的類,所以我將建構式設為私有以防止客戶端Foo直接使用:
#include <memory>
class Foo {
public:
static std::shared_ptr<Foo> Create() {
return std::shared_ptr<Foo>(new Foo());
}
std::shared_ptr<Foo> Copy() {
return std::shared_ptr<Foo>(new Foo(*this));
}
private:
Foo() = default;
};
然后我更新Foo為使用CRTP模式,這樣我就可以Bar從它繼承一個類,而不必重新定義Create()andCopy()方法:
#include <memory>
template <class Self>
class Foo {
public:
template <class... Args>
static std::shared_ptr<Self> Create(Args&&... args) {
return std::shared_ptr<Self>(new Self(std::forward<Args>(args)...));
}
virtual std::shared_ptr<Self> Copy() {
return std::shared_ptr<Self>(new Self(*this));
}
private:
Foo() = default;
};
class Bar : public Foo<Bar> {};
然后我需要提供一個非模板FooBase介面,該介面將提供所有派生類共享的一些功能:
#include <memory>
class FooBase {
public:
virtual void DoSomething() =0;
};
template <class Self>
class Foo : public FooBase {
public:
template <class... Args>
static std::shared_ptr<Self> Create(Args&&... args) {
return std::shared_ptr<Self>(new Self(std::forward<Args>(args)...));
}
virtual std::shared_ptr<Self> Copy() {
return std::shared_ptr<Self>(new Self(*this));
}
virtual void DoSomething() override { }
private:
Foo() = default;
};
class Bar : public Foo<Bar> {
public:
virtual void DoSomething() override { }
};
現在我還需要將Copy()方法暴露給介面,但是如果不更改介面的名稱(例如)Foobar,我找不到任何優雅的方法來做到這一點CopyBase()
#include <memory>
class FooBase {
public:
virtual void DoSomething() =0;
// Expose Copy method by using a different name.
virtual std::shared_ptr<FooBase> CopyBase() const =0;
};
template <class Self>
class Foo : public FooBase {
public:
template <class... Args>
static std::shared_ptr<Self> Create(Args&&... args) {
return std::shared_ptr<Self>(new Self(std::forward<Args>(args)...));
}
virtual std::shared_ptr<FooBase> CopyBase() const override {
return Copy();
}
virtual std::shared_ptr<Self> Copy() {
return std::shared_ptr<Self>(new Self(*this));
}
virtual void DoSomething() override { }
private:
Foo() = default;
};
class Bar : public Foo<Bar> {
public:
virtual void DoSomething() override { }
};
這段代碼有效,但我覺得必須有更好的方法來做到這一點。我詳細地公開了我的思考程序,因為我懷疑缺陷可能出在設計中,所以我想知道是否有人可以幫助我對這個問題有不同的看法。
謝謝你的時間!
uj5u.com熱心網友回復:
協變回傳型別僅適用于常規指標或參考,而不適用于智能指標。
CRTP 的另一個問題是類不完整,因此也不能使用協方差。
傳統的方法確實是將克隆分成兩部分,一個虛擬的(私有的)和一個公共的(非虛擬的),類似于:
template <typename Derived, typename Base>
class Clonable : public Base
{
public:
template <class... Args>
static std::shared_ptr<Derived> Create(Args&&... args) {
return std::shared_ptr<Derived>(new Derived(std::forward<Args>(args)...));
}
std::shared_ptr<Derived> Clone() const {
return std::shared_ptr<Derived>(static_cast<Derived*>(vclone()));
}
private:
// Cannot use covariant-type `Derived*` in CRTP as Derived is not complete yet
Base* vclone() const override {
return new Derived(static_cast<const Derived&>(*this));
}
};
接著
class FooBase {
public:
virtual ~FooBase() = default;
virtual void DoSomething() = 0;
// Expose Copy method by using a different name.
std::shared_ptr<FooBase> Clone() const { return std::shared_ptr<FooBase>(vclone()); }
private:
virtual FooBase* vclone() const = 0;
};
class Bar : public Clonable<Bar, FooBase> {
public:
void DoSomething() override { }
};
演示
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/519887.html
標籤:C 仿制药多态性
