将习语复制并交换为引用抽象类的类

Copy-and-Swap idiom for class with references to abstract classes

本文关键字:引用 抽象类 交换 习语 复制      更新时间:2023-10-16

我正在尝试为我的类实现复制和交换习语,因为我需要实现operator=,而且它有引用成员,并且引用只能分配一次,我认为前面提到的习语是一个有效的解决方法。

但现在我得到了一个构建错误:

>c:Program FilesMicrosoft Visual Studio 10.0VCincludeutility(102): error C2259: 'IVariables' : cannot instantiate abstract class
1>          due to following members:
1>          'IVariables::~IVariables(void)' : is abstract
1>          d:svn.dra.workingcopyserialportIVariables.h(6) : see declaration of 'IVariables::~IVariables'
1>          'std::string &IVariables::operator [](const std::string &)' : is abstract
1>          d:svn.dra.workingcopyserialportIVariables.h(7) : see declaration of 'IVariables::operator []'
1>          'unsigned int IVariables::getVariableLength(const std::string &) const' : is abstract
1>          d:svn.dra.workingcopyserialportIVariables.h(8) : see declaration of 'IVariables::getVariableLength'
1>          Message.cpp(32) : see reference to function template instantiation 'void std::swap<IVariables>(_Ty &,_Ty &)' being compiled
1>          with
1>          [
1>              _Ty=IVariables
1>          ]

它指向我这里:

void Swap( CMessage& a, CMessage& b ){
    using std::swap;
    swap( a.m_bIgnoreIncoming, b.m_bIgnoreIncoming );
    swap( a.m_Variables, b.m_Variables );
}

这是习惯用法中的Swap函数,m_Variables实际上是对抽象类的引用。不可能交换那种参考资料吗?如果有Boost解决方案,请告诉我,因为我最近开始使用它。

引用不能交换,只能重新分配。swap将尝试交换被引用的对象(如果使用默认的std::swap,则通过临时对象进行分配)。由于它们引用了一个抽象基类,因此这将失败,因为无法创建临时基类。

如果需要可重新分配的引用,请改用指针。

这里有一个简短而完整的例子,说明了对抽象类型的引用交换

#include <iostream>
class AbstractBase
{
public:
     virtual AbstractBase& clone() const = 0;
     virtual AbstractBase& operator=(const AbstractBase& other) = 0;
     virtual ~AbstractBase() = default;
};
class IntWrapper: public AbstractBase
{
public:
    int val;
public:
    IntWrapper(int v) : val{v} { }
    
    IntWrapper& clone() const
    {
        IntWrapper* new_obj = new IntWrapper(val);
        return *new_obj;
    }
    IntWrapper& operator=(const AbstractBase& other) override
    {
        auto context = static_cast<const IntWrapper&>(other);
        val=context.val;
        return *this;
    }
    ~IntWrapper() override = default;
};
void swap(AbstractBase& a, AbstractBase& b)
{
    AbstractBase& tmp = a.clone();
    a = b;
    b = tmp;
    delete &tmp;
}
int main()
{
    IntWrapper a(3), b(4);
    std::cout << a.val << ", " << b.val << std::endl;  
    swap(a,b);
    std::cout << a.val << ", " << b.val << std::endl;
    return 0;
}

输出:

3, 4
4, 3

==1977== 
==1977== HEAP SUMMARY:
==1977==     in use at exit: 0 bytes in 0 blocks
==1977==   total heap usage: 3 allocs, 3 frees, 73,744 bytes allocated
==1977== 
==1977== All heap blocks were freed -- no leaks are possible
==1977== 
==1977== For lists of detected and suppressed errors, rerun with: -s
==1977== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)