[英]How to implement a copy constructor of the derived class on a vector of pointers to base class which has instances of derived classes?
[英]How to implement a class template that provides functionality to its derived classes to track their instances?
我正在嘗試創建一個抽象的 class 模板(InstanceTracker),如果類需要對其所有實例執行操作的功能,則可以從該模板繼承。 class 包含指向“T”的指針的 static 向量,每次運行 InstanceTracker 構造函數時,我都會推回指向該向量的新指針。 我通過一個返回“T*”的純虛擬 getDerivedPtr() 方法來執行此操作,從 InstanceTracker 派生的每個 class 都必須通過return this;
. 不過,您可能已經看到出了什么問題。 您永遠不能從基本構造函數調用純虛擬 function - 因為它還不存在。 如何為我的 InstanceTracker class 找到解決此問題的方法? 這是 class 的代碼:
#pragma once
#include <vector>
template <typename T>
class InstanceTracker
{
public:
InstanceTracker() noexcept
{
allInstances_.push_back(getDerivedPtr());
}
InstanceTracker(const InstanceTracker& source) noexcept
: InstanceTracker()
{
}
InstanceTracker(const InstanceTracker&& source) noexcept
: InstanceTracker()
{
}
virtual ~InstanceTracker() noexcept
{
auto it = std::find(allInstances_.begin(), allInstances_.end(), this);
int index = it - allInstances_.begin();
allInstances_.erase(allInstances_.begin() + index);
}
virtual T* getDerivedPtr() = 0;
protected:
static std::vector<T*> allInstances_;
};
如果您想嘗試運行代碼並查看為什么它現在不起作用,這里有一個簡單的 class 繼承自 InstanceTracker:
class Derived1 : public InstanceTracker
{
public:
Derived1* getDerivedPtr() override
{
return this;
}
};
你可能最好使用組合而不是 inheritance,但我認為你有充分的理由更喜歡 inheritance。
困難在於,當運行基本 class 構造函數時, this
指針僅是指向基本 class 實例的指針。 派生實例甚至還沒有退出。 (同樣,在銷毀時,object 的派生部分已經未初始化)。 因此,如果您調用虛擬方法,您將獲得基本的 class 實現,而不是派生類的實現。 在您的情況下,基本 class 實現甚至不存在,所以您被卡住了。
您可能可以將基類的this
指針轉換為指向派生 class 的指針,但這不能保證有效,並且可能涉及未定義的行為。
解決此問題的一種方法是存儲指向基類型 ( InstanceTracker *
) 的指針,而不是指向派生類型的指針。 然后你的getDerivedPtr
方法不需要是虛擬的,它可以在安全的情況下進行強制轉換。
template <typename T>
class InstanceTracker {
public:
InstanceTracker() noexcept {
allInstances_.push_back(this);
}
// other constructors elided for space
virtual ~InstanceTracker() noexcept {
std::erase(
std::remove(allInstances_.begin(), allInstances_.end(),
this),
allInstances.end());
}
T* getDerivedPtr() {
return static_cast<T*>(this); // downcast
}
protected:
// allInstances_ stores base class pointers
static std::vector<InstanceTracker*> allInstances_;
};
筆記:
如果您使用 RTTI,運行時類型識別,您可以使用dynamic_cast
而不是static_cast
。 您不應該使用reinterpret_cast
,因為編譯器可能需要調整基指針作為轉換的一部分。
如果您將派生類型的實例創建為const
,您可能會遇到問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.