尝试在经过几层抽象之后交换指针向量中的指针

Attempting to swap pointers in vector of pointers after a few layers of abstraction

本文关键字:指针 交换 抽象 之后 向量 几层 经过      更新时间:2023-10-16

所以我有一个包含基类的指针向量。我在向量中创建了两个元素,然后尝试在几层抽象之后交换它们。目前,这导致编译器爆炸,并在move.h中抛出几个错误,如下所示:

*c:program files (x86)codeblocksmingwbin../lib/gcc/mingw32/4.4.1/include/c++/bits/move.h: In function 'void std::swap(_Tp&, _Tp&) [with _Tp = Base]':
D:My Documentspointertest2main.cpp:52:   instantiated from here
c:program files (x86)codeblocksmingwbin../lib/gcc/mingw32/4.4.1/include/c++/bits/move.h:81: error: cannot allocate an object of abstract type 'Base'
D:My Documentspointertest2main.cpp:7: note:   because the following virtual functions are pure within 'Base':
D:My Documentspointertest2main.cpp:11: note:     virtual int Base::GetInt()
c:program files (x86)codeblocksmingwbin../lib/gcc/mingw32/4.4.1/include/c++/bits/move.h:81: error: cannot declare variable '__tmp' to be of abstract type 'Base'
D:My Documentspointertest2main.cpp:7: note:   since type 'Base' has pure virtual functions*

导致此问题的代码如下:

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
class Base {
  public:
    virtual int GetInt() = 0;
    int a;
};
class Test : public Base {
  public:
    int GetInt()
    {
        return a;
    }
};
class Slot {
  public:
    Base *connected;
};
int main()
{
    std::vector<Base*> testVec;
    Base *test = new Test;
    testVec.push_back(test);
    testVec[0]->a = 1;
    Base *test2 = new Test;
    testVec.push_back(test2);
    testVec[1]->a = 2;
    Slot slot;
    slot.connected = testVec[0];
    Slot slot2;
    slot2.connected = testVec[1];
    Slot* slottemp = &slot;
    Slot* slottemp2 = &slot2;
    std::swap(*slottemp->connected, *slottemp2->connected);
    cout << testVec[0]->GetInt() << endl;
    cout << testVec[1]->GetInt() << endl;
    return 0;
}

您可以在最后看到,我希望testVec[0]将返回2,testVec[1]将返回1,因为这些是我正在寻找的交换值。

如果有任何帮助,我将不胜感激,我的头在这个爆炸。我对交换作为元素0和1包含的指针的替代方法持完全开放的态度,这正是我迄今为止所做的。

您正在尝试交换类型为Base的对象。

slottemp->connected的类型是Base *,所以通过交换*slottemp->connected,就交换了两个Base &。由于Base &没有std::swap重载,编译器会返回到默认值,如下所示:

template <class T> void swap ( T& a, T& b )
{
  T c(a); a=b; b=c;
}

如果我们在T = Base上实例化它,那么我们尝试为交换构建一个临时Base;这是失败的,因为Base具有纯虚拟功能。

一种选择是为Base:写入std::swap过载

namespace std {
void swap(Base &a, Base &b) {
  std::swap(a.a, b.a);
}
}

这将允许您交换底层的Base s。然而,这不太可能很适合虚拟基类——如果有人试图交换FooBar,这两个都是从Base派生的,会发生什么?

如果你只想交换Slot,你可以交换Base *,而不是Base本身:

std::swap(slottemp->connected, slottemp2->connected);

如果您希望更改反映在vector中,则应使Slot包含迭代器,或指向向量内指针的指针

class Slot {
  public:
    Base **connected;
};
// ...
slot.connected = &testVec[0];
// ...
std::swap(*slot.connected, ...);

在这种特殊的情况下,您知道真正的类型是Test,所以您也可以转换为这种具体的类型并以这种方式交换:

std::swap(*(Test *)slottemp->connected, *(Test *)slottemp2->connected);

我不推荐这种方法,因为如果您开始向向量中添加Test以外类型的值,它可能会在以后进行切片(或者更糟的是,非法强制转换(。

我想说的是,你试图交换对象而不是指针(*是在连接点处获得对象,而不是作为ptr连接(,而交换不能做到这一点,因为只有具体对象可以交换,它们必须有大小,抽象类没有大小
尝试:

std::swap(slottemp->connected, slottemp2->connected);

以便您只交换指针。

你有

slottempptr(addr01)  -> vec[0]
slottempptr2(addr02) -> vec[1]

你做到了:

swap(slottempptr,slottempptr2)

所以你得到了:

slottempptr2(addr02)  -> vec[1]
slottempptr(addr01)   -> vec[0]

但是vec[0]和vec[1]没有变化,您只是更改了slottempptr