继承自 enable_shared_from_this<...>

swap method for a class inherited from enable_shared_from_this<...>

提问人:traveh 提问时间:10/20/2022 最后编辑:traveh 更新时间:10/20/2022 访问量:46

问:

我已经为我的类实现了一个 swap 方法,该方法继承自enable_shared_from_this<...>

class X : public enable_shared_from_this<X> {
    int x;
    friend void swap(X& x1, X& x2) {
        using std::swap;
        swap(x1.x, x2.x);
    }
    X& operator=(X other) {
       swap(*this, other);
    }
    ...
}

我试图通过添加以下任一方法来交换方法中的部分:enable_shared_from_this<...>swap

std::enable_shared_from_this<X>::swap(first, second);

由于以下原因无法编译:

“std::enable_shared_from_this”中没有名为“swap”的成员

swap(static_cast<std::enable_shared_from_this<X>>(first), static_cast<std::enable_shared_from_this<X>>(second));

由于以下原因无法编译:

调用类“std::enable_shared_from_this”的受保护构造函数的受保护构造函数只能用于构造基类子对象

最后,我求助于在赋值运算符中添加以下行:

std::enable_shared_from_this<X>::operator=(other);

但这对我来说是错误的,因为该方法不完整,并且通常混合了两个成语(我猜)。swap

那么处理这个问题的正确方法是什么......?

注意:我使用的是 C++20。

C++ C++20 复制和交换 enable-shared-from-this

评论

0赞 Barry 10/20/2022
你到底想做什么?这里应该是一个吗?swapfriend
0赞 traveh 10/20/2022
@Barry 是的,对不起,我忘了添加它。现在做到了。

答:

2赞 Nicol Bolas 10/20/2022 #1

enable_shared_from_this从技术上讲,它有一个复制构造函数和赋值运算符。但它们并没有有意义的作用。它们都不会复制内部成员。因此,即使在分配之后,也会是一样的。weak_thisweak_this

交换不是支持的功能。enable_shared_from_this

请注意,交换它们实际上没有意义。管理每个对象的内存指向它们管理的特定对象。交换对象仅交换其内容;两个对象的地址保持不变。因此,托管存储仍应引用原始对象,因为它们的地址没有更改。shared_ptr

因此,您不能 “复制” 或 “交换” 是有道理的。因此,只需保留基类子对象即可。enable_shared_from_this

评论

0赞 traveh 10/20/2022
如果我的共享指针为此类的所有对象共享相同的资源,这对我来说是有意义的,但在我的情况下,共享指针(不一定)这样做......(在对象被复制/移动/分配的情况下,它们应该是相同的,但当我想交换它们时不一定......事实上,我的情况有点复杂,有多个虚拟继承,但我认为这部分没有关系......如果是,我会发布另一个问题,提供更多细节......
0赞 Nicol Bolas 10/20/2022
你说的没有意义。您有两个对象,A 和 B。它们中的每一个都有单独的共享状态。该共享状态包含 A 和 B 的地址。如果交换 A 和 B 的内容...他们的地址不会改变。即使从逻辑上讲,A 现在具有旧 B 的内容和行为,它仍然是对象 A,而不是对象 B。它不会变成 B;它只包含 B 的旧数据。共享状态仍然指向 A,而不是 B。
0赞 Nicol Bolas 10/20/2022
@traveh:您无法更改由共享状态本身管理的指针。他们甚至不是 .enable_shared_from_this
0赞 Nicol Bolas 10/20/2022
@traveh:“我的情况有点复杂,多重虚拟继承”无关紧要。不能在逻辑上交换不同类型的对象。我的意思是,你可以让它在技术上起作用,但你已经远远超出了“交换”的实际含义。
0赞 traveh 10/21/2022
哦,我想我明白了......但是,如果其中一个实际上是空的(即nullptr)......呢?在这种情况下,我应该用一个空状态填充它,并将空状态的内容与另一个状态交换?