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

时间:2011-07-17 19:12:22

标签: c++

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

*c:\program files (x86)\codeblocks\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/move.h: In function 'void std::swap(_Tp&, _Tp&) [with _Tp = Base]':
D:\My Documents\pointertest2\main.cpp:52:   instantiated from here
c:\program files (x86)\codeblocks\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/move.h:81: error: cannot allocate an object of abstract type 'Base'
D:\My Documents\pointertest2\main.cpp:7: note:   because the following virtual functions are pure within 'Base':
D:\My Documents\pointertest2\main.cpp:11: note:     virtual int Base::GetInt()
c:\program files (x86)\codeblocks\mingw\bin\../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 Documents\pointertest2\main.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中的指针的替代方法,这就是我到目前为止所处的位置。

2 个答案:

答案 0 :(得分:2)

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

slottemp->connected属于Base *类型,因此通过交换*slottemp->connected,您需要交换两个Base &。由于std::swap没有Base &重载,编译器会回退到默认值,如下所示:

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

如果我们在T = Base上实例化,那么我们会尝试为交换构建一个临时Base;这失败了,因为Base具有纯虚函数。

一种选择是为std::swap写一个Base重载:

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

这将允许您交换基础Base。但是,这不太适合虚拟基类 - 如果有人试图交换来自Foo的{​​{1}}和Bar,会发生什么?

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

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); 以外的类型值,它会引发slicing(或更糟糕的是,非法转换)的可能性。

答案 1 :(得分:0)

我会说你正在尝试交换对象而不是指针(*正在获取连接点的对象,而不是作为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