C++ 使用“隐藏基类方法”;使用;声明不';不为赋值运算符工作
下面是如何在派生类中使用基本方法的简单示例:C++ 使用“隐藏基类方法”;使用;声明不';不为赋值运算符工作,c++,operator-overloading,using,language-lawyer,method-hiding,C++,Operator Overloading,Using,Language Lawyer,Method Hiding,下面是如何在派生类中使用基本方法的简单示例: struct Base { void foo (); Base& operator = (const Base&); }; struct Derived : Base { // ... }; int main () { Derived d1, d2; d1.foo(); // calls Base::foo d1 = d2; // calls Base::operator = } 如果我在Deriv
struct Base {
void foo ();
Base& operator = (const Base&);
};
struct Derived : Base {
// ...
};
int main () {
Derived d1, d2;
d1.foo(); // calls Base::foo
d1 = d2; // calls Base::operator =
}
如果我在Derived
的主体中添加以下语句以隐藏这两个方法
struct Derived : Base {
//...
private: // hide the below method for `Derived` objects
using Base::foo;
using Base::operator =;
}
。。。然后,成功隐藏了Base::foo()
。但是
Base::operator=
仍然可以访问
同样的现象也发生在其他运营商身上。这是一本书
可访问性规则(由于使用
关键字而应用)不应该以同样的方式应用于方法和运算符吗?如果不是,那么语句的意义是什么:
usingoperator=代码>,编译器是否忽略了它
更新:
我的第一个想法是,编译器可能正在生成自己的
默认值派生::运算符=
。这是错误的,因为它使用
Base::operator=
李>
如果我使用private
继承,那么Base::foo()
将自动
隐藏(即使没有使用)。但对Base::operator=
没有影响,
它仍然有效
请注意,我不想要“如何隐藏它”的解决方案。但我想从语言的角度理解,为什么操作符不像其他方法一样隐藏。编译器将为派生类生成一个默认的操作符=
,这个隐式的派生::操作符=
反过来在内部调用基::操作符=
。
要消除此问题,我们需要显式禁用运算符=
:
struct Derived : Base {
private: Derived& operator = (const Derived&); // C++03 way
};
struct Derived : Base {
Derived& operator = (const Derived&) = delete; // C++11 way
};
编译器将为派生类生成一个默认的运算符=
,这个隐式的派生的::运算符=
依次在内部调用基::运算符=
。
要消除此问题,我们需要显式禁用运算符=
:
struct Derived : Base {
private: Derived& operator = (const Derived&); // C++03 way
};
struct Derived : Base {
Derived& operator = (const Derived&) = delete; // C++11 way
};
更新:
我的第一个想法是,编译器可能正在生成自己的默认派生::运算符=。这是错误的,因为它使用Base::operator=
。其他运营商也是如此
如果我使用私有继承,那么Base::foo()
将自动隐藏(即使不使用)。但对Base::operator=
没有影响,它仍然有效
你的第一个想法是正确的。您没有声明复制赋值运算符,因此隐式为您声明了一个。然后,odr使用隐式声明的复制赋值运算符,因此编译器提供了隐式定义的复制赋值运算符。结构或类的隐式定义的复制赋值运算符执行类基类的成员复制赋值,然后执行非静态数据成员的复制赋值
隐式定义的复制赋值运算符是类成员。通过使用
或通过私有继承将基类复制构造函数隐藏到外部世界一点都不重要,因为该基类赋值运算符对该隐式定义的复制赋值运算符可见
更新:
我的第一个想法是,编译器可能正在生成自己的默认派生::运算符=。这是错误的,因为它使用Base::operator=
。其他运营商也是如此
如果我使用私有继承,那么Base::foo()
将自动隐藏(即使不使用)。但对Base::operator=
没有影响,它仍然有效
你的第一个想法是正确的。您没有声明复制赋值运算符,因此隐式为您声明了一个。然后,odr使用隐式声明的复制赋值运算符,因此编译器提供了隐式定义的复制赋值运算符。结构或类的隐式定义的复制赋值运算符执行类基类的成员复制赋值,然后执行非静态数据成员的复制赋值
隐式定义的复制赋值运算符是类成员。通过使用
或通过私有继承将基类复制构造函数隐藏到外部世界一点都不重要,因为该基类赋值运算符对该隐式定义的复制赋值运算符可见。这是因为没有理由查找基类运算符。派生类已经隐式地有了一个完全可用的赋值运算符。@KerrekSB,我已经在问题中澄清了这一部分。它不使用编译器生成的运算符=
。似乎还有其他原因。让我们暂时不使用编译器,它并没有真正发挥作用。隐式定义的运算符=
执行成员式赋值,还调用基类的赋值运算符,因此您可能不一定能够判断。如果将基类赋值运算符设为私有,则隐式定义的派生赋值运算符定义为已删除。@KerrekSB,是的,你的第二条评论对我来说很有意义。编译器应该调用隐式的Derived::operator=
,它反过来隐式地调用Base::operator=
。这是因为没有理由查找基运算符。派生类已经隐式地有了一个完全可用的赋值运算符。@KerrekSB,我已经在问题中澄清了这一部分。它不使用编译器生成的运算符=
。似乎还有其他原因。让我们暂时不使用编译器,它并没有真正发挥作用。隐式定义的运算符=
执行成员式赋值,还调用基类的赋值运算符,因此您可能不一定能够判断。如果将基类赋值运算符设为私有,则隐式定义的派生赋值运算符定义为已删除。@KerrekSB,是的,你的第二条评论对我来说很有意义。编译器应该调用隐式Derived::operator=
,该操作符反过来隐式调用Ba