我正在实现一个通用接口,可以桥接某些基类的不同实现。
接口实用程序编写如下:
// InterfaceUtils.h
//
// Base object class
class IBaseObject {
virtual ~IBaseObject() = default;
};
// Unknown object adapter
class UnknownObject
{
public:
UnknownObject() = default;
UnknownObject(const UnknownObject& from);
UnknownObject(UnknownObject&& from) noexcept;
explicit UnknownObject(const IBaseObject& from);
explicit UnknownObject(IBaseObject* from)
{
SetPointer(from);
}
virtual ~UnknownObject()
{
DeletePointer();
}
template<class Interface>
const Interface* RetrieveInterface() const
{
if (!m_pObject)
return nullptr;
return dynamic_cast<const Interface*>(m_pObject);
}
template<class Interface>
Interface* RetrieveInterface()
{
if (!m_pObject)
return nullptr;
return dynamic_cast<Interface*>(m_pObject);
}
UnknownObject& operator=(const UnknownObject& other);
UnknownObject& operator=(UnknownObject&& other) noexcept;
[[nodiscard]] bool IsNull() const
{
return m_pObject == nullptr;
}
void SetNull();
protected:
[[nodiscard]] virtual const IBaseObject* GetPointer() const
{
return m_pObject;
}
virtual IBaseObject* GetPointer()
{
return m_pObject;
}
void SetPointer(ISymplektBaseObject* pObject)
{
m_pObject = pObject;
}
void DeletePointer() const
{
// Q: Unsafe for memory leaks ?
// delete m_pObject;
}
private:
//>! stored pointer to object
IBaseObject* m_pObject = nullptr;
};
// Generic object interface template
template <class Interface>
class ObjectInterface : public UnknownObject
{
public:
explicit ObjectInterface(const IBaseObject& other)
: UnknownObject(other) { }
explicit ObjectInterface(IBaseObject* other)
: UnknownObject(other) { }
explicit ObjectInterface(const UnknownObject& other)
: UnknownObject(other.RetrieveInterface<Interface>() != nullptr ? other : UnknownObject()) { }
explicit ObjectInterface(UnknownObject&& other) noexcept
: UnknownObject(other.RetrieveInterface<Interface>() != nullptr ? std::move(other) : UnknownObject()) { }
ObjectInterface(const ObjectInterface<Interface>& other)
: UnknownObject(other) { }
ObjectInterface(ObjectInterface<Interface>&& other) noexcept
: UnknownObject(std::move(other)) { }
~ObjectInterface() override
{
UnknownObject::~UnknownObject();
}
ObjectInterface& operator=(const ObjectInterface<Interface>& other)
{
return UnknownObject::operator=(other);
}
Interface* operator->()
{
return GetInterface();
}
const Interface* operator->() const
{
return GetInterface();
}
Interface* GetInterface()
{
return RetrieveInterface<Interface>();
}
const Interface* GetInterface() const
{
return RetrieveInterface<Interface>();
}
};
如果有什么用,我也会写 *.cpp 的内容:
// InterfaceUtils.cpp
//
#include "InterfaceUtils.h"
void UnknownObject::DeleteInterface(UnknownObject& obj)
{
if (obj.IsNull())
return;
obj.SetNull();
}
UnknownObject::UnknownObject(const UnknownObject& from)
{
if (auto* fromObj = from.GetPointer(); fromObj != nullptr)
{
SetPointer(const_cast<IBaseObject*>(fromObj));
return;
}
SetPointer(nullptr);
}
UnknownObject::UnknownObject(UnknownObject&& from) noexcept
{
SetPointer(from.GetPointer());
from.SetPointer(nullptr);
}
UnknownObject::UnknownObject(const IBaseObject& from)
{
auto* pObject = &from;
SetPointer(const_cast<IBaseObject*>(pObject));
}
UnknownObject& UnknownObject::operator=(const UnknownObject& other)
{
if (this == &other)
return *this;
if (auto* fromObj = other.GetPointer(); fromObj != nullptr)
SetPointer(const_cast<IBaseObject*>(fromObj));
else
SetPointer(nullptr);
return *this;
}
UnknownObject& UnknownObject::operator=(UnknownObject&& other) noexcept
{
DeletePointer();
SetPointer(other.GetPointer());
other.SetPointer(nullptr);
return *this;
}
void UnknownObject::SetNull()
{
DeletePointer();
m_pObject = nullptr;
}
classes 的目的IBaseObject
是能够扩展到不同的实现UnknownObject
,例如:ObjectInterface<>
IBaseObject
class ITestClass : public IBaseObject
{
public:
ITestClass() : IBaseObject() {}
ITestClass(const double& val)
: IBaseObject(), m_Value(val) { }
void SetValue(const double& val)
{
m_Value = val;
}
[[nodiscard]] double GetValue() const
{
return m_Value;
}
[[nodiscard]] virtual double ProcessValue() const = 0;
protected:
double m_Value = 0.0;
};
//
// test class implementation returning m_Value^2 with ProcessValue
//
class TestClassSquareImpl : public ITestClass
{
public:
~TestClassSquareImpl() override
{}
TestClassSquareImpl(const double& val)
: ITestClass(val) {}
[[nodiscard]] double ProcessValue() const override
{
return m_Value * m_Value;
}
};
//
// test class implementation returning sqrt(m_Value) with ProcessValue
//
class TestClassSqrtImpl : public ITestClass
{
public:
~TestClassSqrtImpl() override
{}
TestClassSqrtImpl(const double& val)
: ITestClass(val)
{
}
[[nodiscard]] double ProcessValue() const override
{
return sqrt(m_Value);
}
};
使用如下:
const double dataValue = 3.0;
const auto testObjSqr = TestClassSquareImpl(dataValue);
const auto testObjSqrt = TestClassSqrtImpl(dataValue);
const auto iTestObjSqr = ObjectInterface<ITestClass>(testObjSqr);
const auto iTestObjSqrt = ObjectInterface<ITestClass>(testObjSqrt);
std::cout << iTestObjSqr->ProcessValue() << "\n"; // out: 9.0
std::cout << iTestObjSqrt->ProcessValue() << "\n"; // out: 1.73205080...
问题是:根据我以前的经验,方法UnknownObject::DeletePointer
应该删除 rawm_pObject
以避免内存泄漏,但是这样做时会引发异常,因为派生实例的内存块即将被释放。m_pObject
不删除指针是否安全?UnknownObject
销毁后还是会被删除吗?
inb4:我已经尝试过使用std::unique_ptr
并std::shared_ptr
导致无法从派生实现(例如TestClassSquareImpl::ProcessValue
or ITestClass::GetValue
)访问方法。
编辑:抛出的异常free
是:Invalid address specified to RtlValidateHeap( 0000016F756B0000, 00000004B0AFF988 )
。我在 gtest 中运行示例时第一次遇到它,但是当程序超出范围时会发生同样的事情,从而导致DeletePointer
调用。