我正在编写一个将要连接到数据库的类。所以我有一个全局变量std::shared_ptr<sql::Driver> driver;
,因为我试图学习如何用智能指针做所有事情。但这始终是一个问题,到目前为止每个智能指针,因为sql::Driver
的析构函数受到保护。所以像driver.reset( )
这样的呼叫总是会遇到问题。如何将智能指针与sql::Driver
组合?
答案 0 :(得分:2)
简而言之,有些课程并非由某些外部来电者(即你)管理。
某些类的设计方式是作为副作用发生破坏:
void finished() {
// Do something...
delete this;
}
在其他情况下,这些类可能由某个朋友级管理,如实例管理器或某种类型。受保护的析构函数可能意味着您需要扩展该类以获得许可。
沿着这些方向,单例类不能被实例化,也不能存储在任何类型的智能指针中,因为构造函数通常是私有的;
class Singleton {
private:
Singleton() { //...
}
};
这些类型的类与智能指针不兼容,因为它不允许正确的引用计数。
答案 1 :(得分:2)
Connector/C++ Connecting to MySQL部分说明您没有明确<c:set>
,这就是您获得delete driver
的原因。因此,解决方案是使用error: ‘virtual sql::Driver::~Driver()’ is protected
的哑指针而不是智能指针。 (仅适用于driver
!)
driver
,Connection
和Statement
对智能指针没有任何问题:
ResultSet
请注意,Connector/C++ Complete Example 1和Connector/C++ Complete Example 2 // a dumb pointer is used here intentionally, no need to delete it
sql::Driver* driver = get_driver_instance();
// shared_ptr also works
unique_ptr<sql::Connection> con( driver->connect("tcp://127.0.0.1:3306", "root", "root") );
不会被删除。
答案 2 :(得分:0)
您要做的只是完全错误。你提到如果你使用普通指针,你根本就不会调用delete
。这与析构函数为protected
的事实一起暗示了您没有指针值的所有权这一事实。
由于您没有所有权,因此您与unique_ptr
和/或shared_ptr
无关,后者处理指向的值的唯一且共享所有权。
如果你坚持继续这条路线,并增加相当大的开销来保持同步的参考计数你甚至不需要,那么你就可以做到。 unique_ptr
和shared_ptr
都可以使用 Deleter 参数。在您的情况下,正如您已经提到的那样,它将是 no-op 。
struct noop_deleter
{
void operator ()(void const* ptr) const { /*no-op*/ };
};
shared_ptr<sql::driver>{ driver_ptr, noop_deleter{} };
unique_ptr<sql::driver, noop_deleter>{ driver_ptr, noop_deleter{} };
答案 3 :(得分:0)
如果它受到保护,它要么被继承,要么你应该调用一个静态的Destroy()函数(或类似的)进行破坏。对于前者,您可以执行以下操作:
class MyDriver : public sql::Driver
{
public:
virtual ~MyDriver() {} // calls sql::Driver::~Driver() implicitly
// ...
};
也许SQL库中的一些具体类可以满足您的需求。在这种情况下,请查看如何使用它们。
对于销毁功能,您使用自定义删除器。假设这样的事情:
namespace sql
{
class Driver
{
public:
static Driver* Create(); // factory
static void Destroy( Driver* );
// ...
protected:
Driver();
virtual ~Driver();
};
}
你会这样做:
std::shared_ptr<sql::Driver> driver(
sql::Driver::Create(),
sql::Driver::Destroy );
但一般情况下,您的destructors should either be public and virtual or private and non-virtual。
第三个选项是你的sql :: Driver应该是一个单例,虽然dtor应该仍然是私有的,除非它是为继承而设计的。