引用抽象类的类的复制和交换习惯用法

发布于 2024-12-26 16:09:25 字数 1592 浏览 3 评论 0原文

我正在尝试实现 Copy-and-Swap Idiom我的类,因为我需要实现 operator=,并且由于它具有引用成员,并且引用只能分配一次,所以我认为上述习惯用法是一个有效的解决方法。

但现在我遇到了构建错误:

>c:\Program Files\Microsoft Visual Studio 10.0\VC\include\utility(102): error C2259: 'IVariables' : cannot instantiate abstract class
1>          due to following members:
1>          'IVariables::~IVariables(void)' : is abstract
1>          d:\svn.dra.workingcopy\serialport\IVariables.h(6) : see declaration of 'IVariables::~IVariables'
1>          'std::string &IVariables::operator [](const std::string &)' : is abstract
1>          d:\svn.dra.workingcopy\serialport\IVariables.h(7) : see declaration of 'IVariables::operator []'
1>          'unsigned int IVariables::getVariableLength(const std::string &) const' : is abstract
1>          d:\svn.dra.workingcopy\serialport\IVariables.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 解决方案,请告诉我,因为我最近开始使用它。

I'm trying to implement the Copy-and-Swap Idiom for my class, because I need to implement operator=, and since it has reference members, and references can only be assigned once, I thought that the aforementioned idiom was a valid workaround.

But now I'm getting a build error:

>c:\Program Files\Microsoft Visual Studio 10.0\VC\include\utility(102): error C2259: 'IVariables' : cannot instantiate abstract class
1>          due to following members:
1>          'IVariables::~IVariables(void)' : is abstract
1>          d:\svn.dra.workingcopy\serialport\IVariables.h(6) : see declaration of 'IVariables::~IVariables'
1>          'std::string &IVariables::operator [](const std::string &)' : is abstract
1>          d:\svn.dra.workingcopy\serialport\IVariables.h(7) : see declaration of 'IVariables::operator []'
1>          'unsigned int IVariables::getVariableLength(const std::string &) const' : is abstract
1>          d:\svn.dra.workingcopy\serialport\IVariables.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>          ]

It points me here:

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

This is the Swap function from the idiom, and m_Variables is indeed a reference to an abstract class. Is it impossible to swap that kind of references? If there is a Boost solution for this, please tell me since I recently started using it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

上课铃就是安魂曲 2025-01-02 16:09:25

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

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

References can't be swapped any more than they can be reassigned. swap will attempt to swap the objects being referred to (by assigning them via a temporary object, if the default std::swap is used). Since they refer to an abstract base class, then this fails since the temporary can't be created.

If you want a reassignable reference, then use a pointer instead.

冷清清 2025-01-02 16:09:25

这是一个简短而完整的示例,说明了交换对抽象类型的引用:

#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)

Here is a short and complete example that illustrates swapping references to abstract type:

#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;
}

And output:

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文