如何将sql :: driver与智能指针结合起来?

时间:2013-06-18 18:21:54

标签: c++ smart-pointers

我正在编写一个将要连接到数据库的类。所以我有一个全局变量std::shared_ptr<sql::Driver> driver;,因为我试图学习如何用智能指针做所有事情。但这始终是一个问题,到目前为止每个智能指针,因为sql::Driver的析构函数受到保护。所以像driver.reset( )这样的呼叫总是会遇到问题。如何将智能指针与sql::Driver组合?

4 个答案:

答案 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!)

driverConnectionStatement对智能指针没有任何问题:

ResultSet

请注意,Connector/C++ Complete Example 1Connector/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_ptrshared_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应该仍然是私有的,除非它是为继承而设计的。