所以我有一个包含基类的指针向量。我在向量中创建了两个元素,然后尝试在几层抽象之后交换它们。目前这会导致编译器爆炸并在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中的指针的替代方法,这就是我到目前为止所处的位置。
答案 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