具有多重继承的复制赋值操作符
我的复制构造函数工作正常,但我不明白我的复制赋值操作符有什么问题。具有多重继承的复制赋值操作符
#include <iostream>
template <typename... Ts> class foo;
template <typename Last>
class foo<Last> {
Last last;
public:
foo (Last r) : last(r) { }
foo() = default;
foo (const foo& other) : last(other.last) { }
foo& operator= (const foo& other) {
last = other.last;
return *this;
}
};
template <typename First, typename... Rest>
class foo<First, Rest...> : public foo<Rest...> {
First first;
public:
foo (First f, Rest... rest) : foo<Rest...>(rest...), first(f) { }
foo() = default;
foo (const foo& other) : foo<Rest...>(other), first(other.first) { std::cout << "[Copy constructor called]\n"; }
foo& operator= (const foo& other) { // Copy assignment operator
if (&other == this)
return *this;
first = other.first;
return foo<Rest...>::operator= (other);
}
};
int main() {
const foo<int, char, bool> a(4, 'c', true);
foo<int, char, bool> b = a; // Copy constructor works fine.
foo<int, char, bool> c;
// c = a; // Won't compile.
}
错误消息:
error: invalid initialization of reference of type 'foo<int, char, bool>&' from expression of type 'foo<char, bool>'
return foo<Rest...>::operator= (other);
^
能有人在这里指出的问题?
你return语句
return foo<Rest...>::operator= (other);
返回foo<Rest...>
(这是与定义的参考operator=
类型)。但它是从一个应该返回foo<First, Rest...>&
的运营商那里这样做的。
本质上,您返回Base
,其中Derived&
预计参考。参考根本不会绑定。
幸运的是修复很简单:不要返回foo<Rest...>::operator=
的结果,而是返回*this
。
foo& operator= (const foo& other) { // Copy assignment operator
if (&other == this)
return *this;
first = other.first;
foo<Rest...>::operator= (other);
return *this;
}
@故事出纳是的的确如此。作为奖励,'if(&other == this)return * this;'被多次调用,但冗余,正确(它只需要调用一次)?但没办法避免这种情况? – prestokeys
@prestokeys - 您可以随时将'operator ='委派给另一个不检查(并且递归实现)的命名成员。 – StoryTeller
@ StoryTeller答案已被接受,我实现了你的想法,在单独的答案中进行优化。谢谢。 – prestokeys
貌似从operator=
在派生类中返回不正确:
return foo<Rest...>::operator= (other);
它返回基类,而应该是*this
。将其更改为
this -> foo<Rest...>::operator= (other);
return *this;
由于说书人,这里是一个完全优化的编译解决方案(运营商=委托给另一个名为成员名称copy_data
不检查自赋值,并递归执行):
#include <iostream>
template <typename... Ts> class foo;
template <typename Last>
class foo<Last> {
Last last;
public:
foo (Last r) : last(r) { }
foo() = default;
foo (const foo& other) : last(other.last) { }
foo& operator= (const foo& other) {
if (&other == this)
return *this;
last = other.last;
return *this;
}
protected:
void copy_data (const foo& other) {
last = other.last;
}
};
template <typename First, typename... Rest>
class foo<First, Rest...> : public foo<Rest...> {
First first;
public:
foo (First f, Rest... rest) : foo<Rest...>(rest...), first(f) { }
foo() = default;
foo (const foo& other) : foo<Rest...>(other), first(other.first) { std::cout << "[Copy constructor called]\n"; }
foo& operator= (const foo& other) { // Copy assignment operator
if (&other == this)
return *this;
first = other.first;
// foo<Rest...>::operator= (other);
foo<Rest...>::copy_data(other);
std::cout << "[Assignment operator called]\n";
return *this;
}
protected:
void copy_data (const foo& other) {
first = other.first;
foo<Rest...>::copy_data(other);
}
};
int main() {
const foo<int, char, bool> a(4, 'c', true);
foo<int, char, bool> b = a; // Copy constructor works fine.
foo<int, char, bool> c;
c = b; // Copy assignment operator works fine (and optimized).
}
为什么不使用复制和交换?你是否期望'不可交换或可衡量的性能问题? –