這可能不是正是你問什麼;但這可能會實現你的目標。我在這裏有一個抽象基類,它有三個定義的派生類。我在虛擬類型的類中沒有克隆方法,但我所擁有的是一個模板函數,可以爲您完成這項工作。
#include <iostream>
#include <conio.h>
class Base {
public:
enum Type {
TYPE_1 = 0,
TYPE_2,
TYPE_3,
}; // Type
private:
Type m_eType;
public:
virtual ~Base() {}
Type getType() const { return m_eType; }
protected:
explicit Base(Type eType) : m_eType(eType) {}
private:
Base(const Base& c); // Not Implemented
Base& operator=(const Base& c); // Not Implemented
}; // Base
class Derived1 : public Base {
private:
int m_val;
public:
Derived1() : Base(TYPE_1), m_val(0) {}
explicit Derived1(int val) : Base(TYPE_1), m_val(val) {}
virtual ~Derived1() {}
int getValue() const { return m_val; }
void setValue(int val) { m_val = val; }
private:
Derived1(const Derived1& c); // Not Implemented
Derived1& operator=(const Derived1& c); // Not Implemented
}; // Derived1
class Derived2 : public Base {
private:
float m_val;
public:
Derived2() : Base(TYPE_2), m_val(0) {}
explicit Derived2(float val) : Base(TYPE_2), m_val(val) {}
virtual ~Derived2() {}
float getValue() const { return m_val; }
void setValue(float val) { m_val = val; }
private:
Derived2(const Derived2& c); // Not Implemented
Derived2& operator=(const Derived2& c); // Not Implemented
}; // Derived2
class Derived3 : public Base {
private:
double m_val;
public:
Derived3() : Base(TYPE_3), m_val(0) {}
explicit Derived3(double val) : Base(TYPE_3), m_val(val) {}
virtual ~Derived3() {}
double getValue() const { return m_val; }
void setValue(double val) { m_val = val; }
private:
Derived3(const Derived3& c); // Not Implemented
Derived3& operator=(const Derived3& c); // Not Implemented
}; // Derived3
// This Function Template Takes The Base Of The Object And The
// Derived Type For Its Templated Parameters. The Function's
// Parameter Takes A Pointer To The Derived Type And A Bool Flag That Is
// True By Default And Will Make A Complete Clone, If This Is False It Will
// Make A Fresh Clean Object, It Will Construct
// A New Object On The Heap, Then Dynamically Cast It To A Pointer Of
// Its Base And It Will Return Its Base Pointer, Otherwise It Will
// Return nullptr. NOTE: I Did Not Include Any Error Checking To
// See If The Two Templated Types Passed In Are Derived From One Another.
template<class BaseT, class DerivedT>
BaseT* clone(DerivedT* clonerPtr, bool bClone = true) {
BaseT* basePtr = nullptr;
if (bClone) {
DerivedT* pTemp = new DerivedT();
pTemp = clonerPtr; // Will Require operator=() to be defined for the derived classes.
if (pTemp == nullptr) {
return nullptr;
}
basePtr = dynamic_cast<BaseT*>(pTemp);
} else {
// Create New Empty Object.
clonerPtr = new DerivedT();
if (clonerPtr == nullptr) {
return nullptr;
}
basePtr = dynamic_cast<BaseT*>(clonerPtr);
}
return basePtr;
}
int main() {
Base* pBase = nullptr;
// 1st Case Using The Heap
Derived1* ptr1 = new Derived1(5);
pBase = clone<Base, Derived2>(ptr1);
std::cout << pBase->getType() << std::endl;
if (ptr1) {
delete ptr1;
ptr1 = nullptr;
}
if (pBase) {
delete pBase;
pBase = nullptr;
}
// 2nd Case Using Stack Object
pBase = nullptr; // Not need but just incase
Derived2 d2(3.41f);
pBase = clone<Base, Derived2>(&d2);
std::cout << pBase->getType() << std::endl;
if (pBase) {
delete pBase;
pBase = nullptr;
}
std::cout << "Press any key to quit." << std::endl;
_getch();
return 0;
}
另一個提醒是,模板函數和類都不會通過new和delete操作符清除堆中的內存。所以需要謹慎使用這種方法或方法。如果想要實現類似的方法,但不必擔心清理動態內存,那麼應該在函數模板中使用智能指針。
不可以。您可以使用CRTP來減少克隆所需的樣板,但我不會直接稱它爲簡單。但是我敢肯定你可以找到克隆實現的例子,如果你搜索它們。 –
這似乎是一個矛盾的事情(因爲它是一個抽象接口)。你永遠不應該直接實例化一個'AbstractVehicle'。 – CoffeeandCode
@CoffeeandCode這不是這裏的意圖 – ICoffeeConsumer