【发布时间】:2018-08-26 06:00:54
【问题描述】:
我试图派生 std::unique_lock 并且遇到了一个问题,否则我无法使用更简单的类进行复制。下面是复制问题的可编译代码:
#include <iostream>
#include <mutex>
#include <string>
template<class T>
class A : public std::unique_lock<T>
{
public:
template<typename... Args>
A(const std::string name, Args&&... args) : name_(name),
std::unique_lock<T>(args...) { }
virtual ~A() {} // if this destructor exists...
private:
std::string name_;
};
int main()
{
std::timed_mutex tm;
auto a = A<std::timed_mutex>("Hello", tm, std::defer_lock); // this line fails
A<std::timed_mutex> a("Hello", tm, std::defer_lock); // this line works
return 0;
}
如果存在虚拟析构函数(我的实际类需要它),那么我不能使用带有 auto 的行来实例化该类,因为最终调用 std::unique_lock 中的 ctor 是已删除的需要 const T&被删除的互斥锁(b/c 锁类不能处理 const 互斥锁)。我假设它调用了删除的 const ctor,因为由于某种原因,它调用了 A() 中的复制构造函数,该构造函数将 const &A 作为输入(根据下面的错误日志)。如果我只是使用非自动样式的实例化代码(标记),那么它编译得很好。
我正在使用 gcc 5.4.1 设置(CMAKE_CXX_STANDARD 11)设置。我也试过 14 和 17,所以我认为它不是我正在使用的 cpp。
【问题讨论】:
-
如果类从不派生,那么使用虚拟析构函数毫无意义。 (如果你确实从这个类派生它会大大改变问题)
-
这个类肯定是封装而不是派生的候选者吧?
-
虚拟 dtor 的重点是确保基类的 dtor 被调用,这对于 std::unique_lock 很重要。
-
你说的封装,和组合一样吗?为了简洁明了,我发送了一个玩具示例,但我的目的是在构建和销毁此类时进行一些记录以用于调试目的,因此它只是记录一些数据的唯一锁。
-
基类的析构函数始终运行。
virtual析构函数通过指向具有virtual析构函数的父类的指针,确保在对象为deleted 时运行最派生类的析构函数。由于std::unique_lock没有virtual析构函数,如果A通过指向std::unique_lock的指针是deleted,您的析构函数将不会运行。
标签: c++ constructor virtual destructor auto