shared_ptr<interface> 实例中的重载 -> 箭头运算符,接口中没有纯虚拟析构函数
Overload -> arrow operator in shared_ptr<interface> instance with no pure virtual destructor in interface
我正在尝试重载 -> 运算符以最终执行以下代码:
MyInterface *myInstance = (MyInterface *)(new A());
myInstance->Toggle(); //this works wonderfully
std::shared_ptr<Wrapper<MyInterface>> sharedPtrWrapper = std::make_shared<Wrapper<MyInterface>>(myInstance);
//the next line doesn't compile, I would like to achieve something like this, but even
//sharedPtrWrapper.get()->Toggle();
//would be nice to achieve, is this possible?
sharedPtrWrapper->Toggle();
//this works:
sharedPtrWrapper->operator->()->Toggle();
注意:我无法控制MyInterface,无法实现纯虚析构函数。
这是我尝试过的(下面的代码运行):
#import <memory>
#import <iostream>
struct MyInterface {
virtual bool Toggle() = 0;
};
class A : public MyInterface {
public:
bool Toggle() {
stateEnabled = !stateEnabled;
std::cout<<"current state " << stateEnabled << std::endl;
return true;
}
private:
bool stateEnabled = false;
};
template <typename T>
class Wrapper {
private:
T *unsafePointer = nullptr;
public:
Wrapper<T>()
{ }
T *operator->() const {
return unsafePointer;
}
T *getInner() {
return unsafePointer;
}
Wrapper<T>(T *stuff) {
unsafePointer = stuff;
}
~Wrapper<T>() {}
};
int main(int argc, const char * argv[]) {
MyInterface *myInstance = (MyInterface *)(new A());
myInstance->Toggle();
Wrapper<MyInterface> wrapperS(myInstance);
wrapperS->Toggle();
std::shared_ptr<Wrapper<MyInterface>> sharedPtrWrapper = std::make_shared<Wrapper<MyInterface>>(myInstance);
sharedPtrWrapper->operator->()->Toggle();
sharedPtrWrapper.operator->()->operator->()->Toggle();
sharedPtrWrapper.get()->operator->()->Toggle();
(*sharedPtrWrapper).operator->()->Toggle();
return 0;
}
输出:
current state 1
current state 0
current state 1
current state 0
current state 1
current state 0
Program ended with exit code: 0
重申一下:
此代码无法编译:
sharedPtrWrapper->Toggle();
如何编译?
Edit :我正在使用包装器,因为我无法控制 MyInterface,我从库中获取它,shared_ptr<MyInterface> mySharedPointer = std::make_shared<MyInterface>(myInstance);
也无法编译,因为上面提到的接口缺少纯虚拟析构函数。
Edit2:伪代码中的示例库用法:
void firstcallbackFromLib(Framework *framework) {
MyInterface *myInstance = framework->getInstance();
{
Wrapper<MyInterface> wrapperS(myInstance);
std::shared_ptr<Wrapper<MyInterface>> sharedPtrWrapper = std::make_shared<Wrapper<MyInterface>>(wrapperS);
//assign sharedPtrWrapper and framework to static instances
}
}
void myFunction() {
sharedPtrWrapper->Toggle(); //this doesn't work, this is what i'm trying to achieve
sharedPtrWrapper->operator->()->Toggle(); //this ugly thing works
}
void lastUninitCallbackFromLibrary() {
MyInterface *p = sharedPtrWrapper.get()->getInner();
framework->releaseInterface(p);
//etc
}
我对这个问题感到困惑。为什么包装器 class 什么都不做?
如果你想把一个 class 放在共享指针中,但在销毁时做一些不常见的事情:比如,调用执行销毁的 dll 函数,做一些预处理,执行文件关闭而不是删除,或者什么都不做如果这就是你想要的。然后你可以简单地在共享指针实例化时指定它:
https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr - 参见构造选项 5。
问题是,shared_ptr
表现得像一个指针,Wrapper
也是如此。总之,您的代码的行为类似于指向指针的指针。简而言之,您可以调用 (*sharedPtrWrapper)->Toggle();
而不是可憎的 sharedPtrWrapper->operator->()->Toggle();
.
不过要小心:目前还不清楚所有这一切应该实现什么,因为示例代码只是您实际代码的抽象。因此,也许将转发 Toggle()
方法放入 class Wrapper
中会更优雅,但根据此处提供的信息无法判断。
sharedPtrWrapper->Toggle();
无法编译,因为 operator->
链接规则解释得很好 in this answer。原则上:如果您的对象不是指针,则递归调用 operator->
,如果它是指针,则执行成员访问。现在 std::shared_ptr
已重载 operator->
以访问保存在内部的原始 Wrapper<MyInterface>*
指针,当它应用于它时,它会尝试访问不存在的 Toggle
。
为清楚起见,请注意此代码也不会编译:
Wrapper<MyInterface>* wrapper = new Wrapper<MyInterface>(myInstance);
wrapper->Toggle();
不过您可以这样做:
(*sharedPtrWrapper)->Toggle();
您根本不需要包装器。
shared_ptr<MyInterface> mySharedPointer = std::make_shared<MyInterface>();
不会工作,因为 MyInterface
是一个抽象 class。但是,就像你可以做的那样
MyInterface *myInstance = new A();
要有一个指向具体派生对象的MyInterface *
,您可以使用
std::shared_ptr<MyInterface> sharedPtr = std::make_shared<A>();
获取指向具体派生对象的std::shared_ptr<MyInterface>
。然后,您可以使用 sharedPtr
访问 Toggle
就像
sharedPtr->Toggle();
你可以看到在这个 live example
中工作
使用:
struct CleanupMyInterface {
SomeTypeFromLib* somePointerFromLib = nullptr;
void operator()( MyInterface* ptr ) const {
if (somePointerFromLib && ptr)
somePointerFromLib->releaseInterface(ptr);
}
};
std::shared_ptr<MyInterface> sharedPtr( CreateAnInstanceOfAFromLibrary(), CleanupMyInterface{somePointerFromLib} );
shared_ptr
有类型擦除破坏,不需要虚拟析构函数。
我正在尝试重载 -> 运算符以最终执行以下代码:
MyInterface *myInstance = (MyInterface *)(new A());
myInstance->Toggle(); //this works wonderfully
std::shared_ptr<Wrapper<MyInterface>> sharedPtrWrapper = std::make_shared<Wrapper<MyInterface>>(myInstance);
//the next line doesn't compile, I would like to achieve something like this, but even
//sharedPtrWrapper.get()->Toggle();
//would be nice to achieve, is this possible?
sharedPtrWrapper->Toggle();
//this works:
sharedPtrWrapper->operator->()->Toggle();
注意:我无法控制MyInterface,无法实现纯虚析构函数。
这是我尝试过的(下面的代码运行):
#import <memory>
#import <iostream>
struct MyInterface {
virtual bool Toggle() = 0;
};
class A : public MyInterface {
public:
bool Toggle() {
stateEnabled = !stateEnabled;
std::cout<<"current state " << stateEnabled << std::endl;
return true;
}
private:
bool stateEnabled = false;
};
template <typename T>
class Wrapper {
private:
T *unsafePointer = nullptr;
public:
Wrapper<T>()
{ }
T *operator->() const {
return unsafePointer;
}
T *getInner() {
return unsafePointer;
}
Wrapper<T>(T *stuff) {
unsafePointer = stuff;
}
~Wrapper<T>() {}
};
int main(int argc, const char * argv[]) {
MyInterface *myInstance = (MyInterface *)(new A());
myInstance->Toggle();
Wrapper<MyInterface> wrapperS(myInstance);
wrapperS->Toggle();
std::shared_ptr<Wrapper<MyInterface>> sharedPtrWrapper = std::make_shared<Wrapper<MyInterface>>(myInstance);
sharedPtrWrapper->operator->()->Toggle();
sharedPtrWrapper.operator->()->operator->()->Toggle();
sharedPtrWrapper.get()->operator->()->Toggle();
(*sharedPtrWrapper).operator->()->Toggle();
return 0;
}
输出:
current state 1
current state 0
current state 1
current state 0
current state 1
current state 0
Program ended with exit code: 0
重申一下: 此代码无法编译:
sharedPtrWrapper->Toggle();
如何编译?
Edit :我正在使用包装器,因为我无法控制 MyInterface,我从库中获取它,shared_ptr<MyInterface> mySharedPointer = std::make_shared<MyInterface>(myInstance);
也无法编译,因为上面提到的接口缺少纯虚拟析构函数。
Edit2:伪代码中的示例库用法:
void firstcallbackFromLib(Framework *framework) {
MyInterface *myInstance = framework->getInstance();
{
Wrapper<MyInterface> wrapperS(myInstance);
std::shared_ptr<Wrapper<MyInterface>> sharedPtrWrapper = std::make_shared<Wrapper<MyInterface>>(wrapperS);
//assign sharedPtrWrapper and framework to static instances
}
}
void myFunction() {
sharedPtrWrapper->Toggle(); //this doesn't work, this is what i'm trying to achieve
sharedPtrWrapper->operator->()->Toggle(); //this ugly thing works
}
void lastUninitCallbackFromLibrary() {
MyInterface *p = sharedPtrWrapper.get()->getInner();
framework->releaseInterface(p);
//etc
}
我对这个问题感到困惑。为什么包装器 class 什么都不做?
如果你想把一个 class 放在共享指针中,但在销毁时做一些不常见的事情:比如,调用执行销毁的 dll 函数,做一些预处理,执行文件关闭而不是删除,或者什么都不做如果这就是你想要的。然后你可以简单地在共享指针实例化时指定它: https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr - 参见构造选项 5。
问题是,shared_ptr
表现得像一个指针,Wrapper
也是如此。总之,您的代码的行为类似于指向指针的指针。简而言之,您可以调用 (*sharedPtrWrapper)->Toggle();
而不是可憎的 sharedPtrWrapper->operator->()->Toggle();
.
不过要小心:目前还不清楚所有这一切应该实现什么,因为示例代码只是您实际代码的抽象。因此,也许将转发 Toggle()
方法放入 class Wrapper
中会更优雅,但根据此处提供的信息无法判断。
sharedPtrWrapper->Toggle();
无法编译,因为 operator->
链接规则解释得很好 in this answer。原则上:如果您的对象不是指针,则递归调用 operator->
,如果它是指针,则执行成员访问。现在 std::shared_ptr
已重载 operator->
以访问保存在内部的原始 Wrapper<MyInterface>*
指针,当它应用于它时,它会尝试访问不存在的 Toggle
。
为清楚起见,请注意此代码也不会编译:
Wrapper<MyInterface>* wrapper = new Wrapper<MyInterface>(myInstance);
wrapper->Toggle();
不过您可以这样做:
(*sharedPtrWrapper)->Toggle();
您根本不需要包装器。
shared_ptr<MyInterface> mySharedPointer = std::make_shared<MyInterface>();
不会工作,因为 MyInterface
是一个抽象 class。但是,就像你可以做的那样
MyInterface *myInstance = new A();
要有一个指向具体派生对象的MyInterface *
,您可以使用
std::shared_ptr<MyInterface> sharedPtr = std::make_shared<A>();
获取指向具体派生对象的std::shared_ptr<MyInterface>
。然后,您可以使用 sharedPtr
访问 Toggle
就像
sharedPtr->Toggle();
你可以看到在这个 live example
中工作使用:
struct CleanupMyInterface {
SomeTypeFromLib* somePointerFromLib = nullptr;
void operator()( MyInterface* ptr ) const {
if (somePointerFromLib && ptr)
somePointerFromLib->releaseInterface(ptr);
}
};
std::shared_ptr<MyInterface> sharedPtr( CreateAnInstanceOfAFromLibrary(), CleanupMyInterface{somePointerFromLib} );
shared_ptr
有类型擦除破坏,不需要虚拟析构函数。