2

我正在编写一个将连接到数据库的类。所以我有一个全局变量std::shared_ptr<sql::Driver> driver;,因为我正在尝试学习如何使用智能指针来做所有事情。但这总是会导致一个问题,到目前为止,每个智能指针都受到保护,因为 的析构函数sql::Driver是受保护的。所以打电话driver.reset( )总是会遇到问题。如何将智能指针与sql::Driver?

4

4 回答 4

2

简而言之,某些类不打算由某些外部调用者(即您)管理。

有些类的设计方式是破坏作为副作用发生:

void finished() {
  // Do something...
  delete this;
}

在其他情况下,这些类可能由某个朋友类管理,例如实例管理器或某种类型。受保护的析构函数可能意味着您需要扩展该类以获得许可。

按照这些思路,单例类不能被实例化,也不能存储在任何类型的智能指针中,因为构造函数通常是私有的;

class Singleton {
private:
  Singleton() {  //...
  }
};

这些类型的类与智能指针不兼容,因为它不允许正确的引用计数。

于 2013-06-18T18:58:00.513 回答
2

连接器/C++ 连接到 MySQL部分说您不必delete driver明确说明,这就是您获得error: ‘virtual sql::Driver::~Driver()’ is protected. 所以解决方案是使用哑指针driver代替智能指针。(仅适用于driver!)

ConnectionStatement并且ResultSet对智能指针没有任何问题:

// 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") );

请注意,在Connector/C++ Complete Example 1Connector/C++ Complete Example 2 driver中没有删除。

于 2015-12-01T14:00:13.967 回答
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 );

但是,一般来说,您的析构函数应该是 public 和 virtual 或 private 和 non-virtual

第三种选择是你的 sql::Driver 应该是一个单例,尽管 dtor 应该在那里仍然是私有的,除非它是为继承而设计的。

于 2013-06-18T19:19:44.837 回答
0

你试图做的是完全错误的。你提到如果你使用普通指针,你根本不会打电话delete。连同析构函数 isprotected的事实,暗示您没有指针值的所有权这一事实。

由于您没有所有权,因此您与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{} };
于 2013-06-18T18:54:56.607 回答