我已經看到了必須在一個類中實作一個clone方法的問題的解決方案(包括在這個站點中),所以return即使我們只有這個類,它也是一個堆分配的自身克隆Base。
當你必須在很多類中一次又一次地實作相同的方法時,問題就出現了,我記得當你只需要從模板類(命名它Cloneable)繼承時這樣做的一種方法,所以它實作了它,但是我試圖這樣做的方式不起作用:
template<typename T, typename B> class Cloneable{
public:
B* clone(){return new T(*this);}
};
class Bottom {
public:
virtual void sayhi() = 0;
virtual Bottom* clone() = 0;
};
class Middle: public Cloneable<Middle, Bottom>, public Bottom {
public:
void sayhi() override {cout << "Hi from the Middle" << endl;}
};
//class Top: public Middle ...?
int main() {
Bottom* b1 = new Middle();
b1->sayhi();
delete b1;
}
我記得向我展示這個的人實際上只用了一個論點就做到了Cloneable,但無論如何,我會感謝你能想象到的任何方式。
uj5u.com熱心網友回復:
您可以使用好奇的回圈模板模式,其中派生類實際上是從其基類的實體派生的,具體取決于其自身。演示:
#include <iostream>
template<typename T>
class Clonable {
public:
T* clone() {
return new T { * static_cast<T *>(this)};
}
};
template<class T>
class Base : public Clonable<T> {
public:
int x = 2;
virtual ~Base() {}
};
class Derived : public Base<Derived> {
public:
int y = 3;
};
int main() {
Base<Derived> *d = new Derived;
static_cast<Derived *>(d)->y = 6;
Derived *c = d.clone(); // we are even cloning from a Base *!
std::cout << c->x << ' ' << c->y << '\n';
delete c;
delete d;
}
它編譯時沒有警告并正確輸出2 6,證明沒有發生切片。
uj5u.com熱心網友回復:
您Cloneable缺少演員表。this是 a Cloneable *,它需要被強制轉換T *為傳遞給復制建構式。
template<typename T, typename B> class Cloneable : public B
{
public:
B* clone() override { return new T(*static_cast<T*>(this)); }
};
class Base
{
public:
virtual Base* clone() = 0;
};
class Derived : public Cloneable<Derived, Base>
{
};
現場觀看
這不會阻止某人進一步子類化Derived,并忘記clone為該孫子類重新實作。
class Oops : public Derived {};
int main() {
Oops o;
Base * pb = o.clone();
assert(typeid(*pb) != typeid(o));
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/416760.html
標籤:
