声明为受保护的重载运算符=
可以公开访问父类作为公共类的子类。
#include <iostream>
class A {
public:
A(char c) : i(c) {}
char i;
protected:
A& operator=(const A& rdm) {
std::cout << "accessing operator=()" << std::endl;
i = 'x';
return *this;
}
};
class B : public A {
public:
B(char c) : A(c) {}
};
int main(int ac, char** av) {
B a('a');
B b('b');
std::cout << "a.i == " << a.i << std::endl;
a = b;
std::cout << "a.i == "<< a.i << std::endl;
}
编译时没有错误:
$ g++ -Wall -o test_operator ~/test_operator.cpp
$ ./test_operator
a.i == a
accessing operator=()
a.i == x
使用A直接编译。除operator=()
以外的任何其他运算符重载都不会编译。
使用g ++ 4.4.7和7.3.0同时使用c ++ 98和c ++ 17进行测试。
为什么operator=()
在这种情况下可以公开访问?
答案 0 :(得分:6)
B
中有隐式副本分配运算符,public
访问权限。
如果类定义没有显式声明一个复制赋值运算符,则会隐式声明一个。如果类定义声明了移动构造函数或移动赋值运算符,则隐式声明的复制赋值运算符被定义为已删除;否则,它被定义为默认([dcl.fct.def])。如果类具有用户声明的复制构造函数或用户声明的析构函数,则不推荐使用后一种情况。类X的隐式声明的复制赋值运算符将具有
形式X& X::operator=(const X&)
如果
-
B
的每个直接基类X
都有一个复制赋值运算符,其参数类型为const B&
,const volatile B&
或B
,并且- 对于类
X
(或其数组)的M
的所有非静态数据成员,每个这样的类类型都有一个复制赋值运算符,其参数类型为{ {1}},const M&
或const volatile M&
。否则,隐式声明的复制赋值运算符将具有
形式M
换句话说,您的代码就像您有:
X& X::operator=(X&)
此处的更新版本演示了隐式声明的复制赋值运算符函数的行为。它表明class B : public A {
public:
B(char c) : A(c) {}
B& operator=(B const& rhs) { A::operator==(rhs); return *this; }
};
不会继承B
的复制赋值运算符。
A
输出:
#include <iostream>
class A {
public:
A(char c) : i(c) {}
char i;
protected:
A& operator=(const A& rdm) {
std::cout << "accessing A::operator=()" << std::endl;
i = 'x';
return *this;
}
};
class X
{
public:
X& operator=(X const& rhs)
{
std::cout << "accessing X::operator=()" << std::endl;
return *this;
}
};
class B : public A {
public:
B(char c) : A(c) {}
X x;
};
int main(int ac, char** av) {
B a('a');
B b('b');
std::cout << "a.i == " << a.i << std::endl;
a = b;
std::cout << "a.i == "<< a.i << std::endl;
}
隐式声明/定义的复制赋值运算符的行为就像我们有:
a.i == a
accessing A::operator=()
accessing X::operator=()
a.i == x
这符合standard says:
的内容非联合类
B& operator=(B const& rhs) { A::operator==(rhs); this.x = rhs.x; return *this; }
的隐式定义的复制/移动赋值运算符执行其子对象的成员复制/移动分配。X
的直接基类首先按照它们在 base-specifier-list 中声明的顺序分配,然后分配X
的直接非静态数据成员。按照在类定义中声明它们的顺序分配。