我想将交换功能添加到两个现有的C++类中.一个类继承自另一个类.我希望每个类的实例只能与同一个类的实例交换.为了使它成为半混凝土,说我有Foo和Bar课程.Bar继承自Foo.我定义了Foo :: swap(Foo&)和Bar :: swap(Bar&).Bar :: swap委托给Foo :: swap.我希望Foo :: swap只能在Foo实例上工作而Bar :: swap只能在Bar实例上工作:我无法弄清楚如何强制执行此要求.
这是给我带来麻烦的一个例子:
#include <algorithm>
#include <iostream>
struct Foo {
int x;
Foo(int x) : x(x) {};
virtual void swap(Foo &other) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
std::swap(this->x, other.x);
};
};
struct Bar : public Foo {
int y;
Bar(int x, int y) : Foo(x), y(y) {};
virtual void swap(Bar &other) {
std::cout << __PRETTY_FUNCTION__ << " ";
Foo::swap(other);
std::swap(this->y, other.y);
};
};
void display(Foo &f1, Foo &f2, Bar &b34, Bar &b56)
{
using namespace std;
cout << "f1: " << f1.x << endl;
cout << "f2: " << f2.x << endl;
cout << "b34: " << b34.x << " " << b34.y << endl;
cout << "b56: " << b56.x << " " << b56.y << endl;
}
int main(int argc, char **argv)
{
{
Foo f1(1), f2(2);
Bar b34(3,4), b56(5,6);
std::cout << std::endl << "Initial values: " << std::endl;
display(f1,f2,b34,b56);
}
{
Foo f1(1), f2(2);
Bar b34(3,4), b56(5,6);
std::cout << std::endl << "After Homogeneous Swap: " << std::endl;
f1.swap(f2); // Desired
b34.swap(b56); // Desired
display(f1,f2,b34,b56);
}
{
Foo f1(1), f2(2);
Bar b34(3,4), b56(5,6);
std::cout << std::endl << "After Heterogeneous Member Swap: " << std::endl;
// b56.swap(f2); // Doesn't compile, excellent
f1.swap(b34); // Want this to not compile, but unsure how
display(f1,f2,b34,b56);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是输出:
Initial values:
f1: 1
f2: 2
b34: 3 4
b56: 5 6
After Homogeneous Swap:
virtual void Foo::swap(Foo&)
virtual void Bar::swap(Bar&) virtual void Foo::swap(Foo&)
f1: 2
f2: 1
b34: 5 6
b56: 3 4
After Heterogeneous Member Swap:
virtual void Foo::swap(Foo&)
f1: 3
f2: 2
b34: 1 4
b56: 5 6
Run Code Online (Sandbox Code Playgroud)
您可以在最终输出组中看到f1.swap(b34)以可能令人讨厌的方式"切片"b34.我不喜欢在运行时编译或爆炸的罪行.由于涉及到继承,我认为如果我使用非成员或朋友交换实现,我会遇到同样的问题.
如果有帮助,代码可以在键盘上找到.
这个用例的出现是因为我想将swap添加到boost :: multi_array和boost :: multi_array_ref.multi_array继承自multi_array_ref.将multi_arrays与multi_arrays和multi_array_refs与multi_array_refs交换是有意义的.
交换,就像赋值和比较一样,可以很好地处理值类型,并且不适用于类层次结构的基础.
我总是发现最容易遵循Scott Meyer的Effective C++建议,即不从具体类派生,只使叶子类具体化.然后,您可以安全地将swap,operator ==等实现为仅用于叶节点的非虚函数.
虽然可以使用虚拟交换函数,但是拥有虚拟基类的重点是在运行时具有动态行为,因此我认为您正试图在编译时尝试使所有不正确的可能性失败.
如果你想进入虚拟交换路由,那么一种可能的方法就是做这样的事情.
class Base
{
public:
virtual void Swap(Base& other) = 0;
};
class ConcreteDerived
{
virtual void Swap(Base& other)
{
// might throw bad_cast, in this case desirable
ConcreteDerived& cother = dynamic_cast<ConcreteDerived&>(other);bad_cast
PrivateSwap(cother);
}
void PrivateSwap(ConcreteDerived& other)
{
// swap implementation
}
};
Run Code Online (Sandbox Code Playgroud)