这与应用程序的以下设置有关,该应用程序使用* .dll和静态库中的(抽象)功能,并最终导致读取访问冲突(代码下方提供了更多详细信息):
...静态库...
// InterfaceWrap.h
//-----------
// dummy include
#include <SomeTClass.h>
template<typename T>
class InterfaceWrap
{
std::shared_ptr<SomeTClass<T>> m_somePtr;
public:
InterfaceWrap();
~InterfaceWrap();
void AnyAction();
};
template<typename T>
InterfaceWrap<T>::InterfaceWrap() {
m_somePtr = std::make_shared<SomeTClass<T>>();
}
template<typename T>
void InterfaceWrap<T>::AnyAction() {
m_somePtr->SomeAction();
}
... * .dll ...
// Proc.h
//-----------
// correct forward declaration?
class ThisInterface;
#include <InterfaceWrap.h>
class DLL Proc
{
std::shared_ptr<InterfaceWrap <ThisInterface>> m_interfaceWrapPtr;
public:
Proc();
~Proc();
InterfaceWrap<ThisInterface>* GetPtr();
};
// Proc.cpp
//-----------
// what about forward declaration here?
Proc::Proc() {
m_interfaceWrapPtr = std::make_shared<InterfaceWrap<ThisInterface>>();
}
InterfaceWrap<ThisInterface>* Proc::GetPtr() {
return m_interfaceWrapPtr.get();
}
...应用程序...
// main.cpp
//-----------
#include <Proc.h>
// dummy includes
#include <ThisType01.h>
#include <ThisType02.h>
#include <ThisType11.h>
#include <ThisType12.h>
class ThisInterfaceA {
public:
using Type1 = ThisType01;
using Type2 = ThisType02;
};
class ThisInterfaceB { // not needed here but perhaps illustrative
public:
using Type1 = ThisType11;
using Type2 = ThisType12;
};
using ThisInterface = ThisInterfaceA;
int main(int argc, char * argv[])
{
Proc proc;
proc.GetPtr()->AnyAction();
return 0;
}
此构造背后的关键意图是使Proc
和InterfaceWrap
类保持尽可能抽象,即使它们不直接依赖于所选的“接口”(例如ThisInterfaceA
)。此外,我想保留该功能,即Proc
不是模板类。
显然存在问题,但我不确定如何很好地解决它们:
using ThisInterface = ThisInterfaceA
行不起作用,因为它导致dll源代码的编译错误,基本上是说ThisInterface是未知的。但是,如果直接用ThisInterfaceA
代替ThisInterface
而不是这一行,则所有编译和链接都至少可以正常进行。m_interfaceWrapPtr
或m_somePtr
的读取访问冲突。我特别想知道的是,正确应用的前向声明是否能够解决上述问题,并允许保留Proc
是抽象(甚至更多)而不是模板类的功能? / p>
答案 0 :(得分:0)
为什么不使用真实界面和DIP:
struct IAnyAction
{
virtual ~IAnyAction() = default;
virtual void AnyAction() = 0;
};
class Proc
{
std::shared_ptr<IAnyAction> m_interface;
public:
Proc(std::shared_ptr<IAnyAction> anyAction) : m_interface(anyAction) {}
IAnyAction* GetPtr() { return m_interface.get(); }
};
template<typename T>
class InterfaceWrap : public IAnyAction
{
std::shared_ptr<SomeTClass<T>> m_somePtr;
public:
InterfaceWrap();
void AnyAction() override { m_somePtr->SomeAction(); }
};
和
using ThisInterface = ThisInterfaceA; // For easy/quick way to change concrete type for interface
int main()
{
Proc proc(std::make_shared<InterfaceWrap<ThisInterface>>());
proc.GetPtr()->AnyAction();
}
答案 1 :(得分:0)
万一有兴趣的人,下面提供了经过修改的示例代码(从头开始),因为它最终对我有用。 解决方案基本上是answer of Jarod42(也许其他评论中指出的那样,这种总体方法可能不是最优雅的方法。但是,我认为某些目的可能是合理的)。
但是,添加了一点小东西:强制转换指针指针参数。对我来说,这在将原始问题扩展到例如成员AnyAction
且其参数尚未确定但为“已知”类型时很有用。
...静态库...
// InterfaceWrap.h
//-----------
// dummy include
#include <SomeTClass.h>
struct IAnyAction
{
virtual ~IAnyAction() = default;
virtual void AnyAction(void* arg) = 0;
};
template<typename T>
class InterfaceWrap : public IAnyAction
{
std::shared_ptr<SomeTClass<T>> m_somePtr;
public:
InterfaceWrap();
void AnyAction(void* arg);
};
template<typename T>
InterfaceWrap<T>::InterfaceWrap(){
m_somePtr = std::make_shared<SomeTClass<T>>();
}
template<typename T>
void InterfaceWrap<T>::AnyAction(void* arg) override {
auto thisArg = static_cast<T::Type1*>(arg);
m_somePtr->SomeAction(*thisArg);
}
... * .dll ...
// Proc.h
//-----------
#include <InterfaceWrap.h>
class DLL Proc
{
std::shared_ptr<IAnyAction> m_interfaceWrapPtr;
public:
Proc(std::shared_ptr<IAnyAction> interfaceWrapPtr);
~Proc();
IAnyAction* GetPtr();
};
// Proc.cpp
//-----------
Proc::Proc(std::shared_ptr<IAnyAction> interfaceWrapPtr) : m_interfaceWrapPtr(interfaceWrapPtr) {
}
IAnyAction* Proc::GetPtr() {
return m_interfaceWrapPtr.get();
}
...应用程序...
// main.cpp
//-----------
#include <Proc.h>
// dummy includes
#include <ThisType01.h>
#include <ThisType02.h>
#include <ThisType11.h>
#include <ThisType12.h>
class ThisInterfaceA {
public:
using Type1 = ThisType01;
using Type2 = ThisType02;
};
class ThisInterfaceB { // not needed here but perhaps illustrative
public:
using Type1 = ThisType11;
using Type2 = ThisType12;
};
using ThisInterface = ThisInterfaceA;
int main(int argc, char * argv[])
{
Proc proc(std::make_shared<InterfaceWrap<ThisInterface>>());
auto type1 = std::make_shared<ThisInterface::Type1*>();
proc.GetPtr()->AnyAction(type1.get());
return 0;
}