为什么我无法从基类的实例访问受保护的成员?
Why can't I access a protected member from an instance of a base class?
假设我有这样的代码:
class foo{
protected:
int a;
};
class bar : public foo {
public:
void copy_a_from_foo(foo& o){
a = o.a; // Error
}
void copy_a_from_bar(bar& o){
a = o.a; // OK
}
};
int main(){
bar x;
foo y;
bar z;
x.copy_a_from_foo(y);
x.copy_a_from_bar(z);
}
这里class bar
从同一类的另一个实例访问受保护成员a
没有问题,但当我尝试对基类foo
的实例执行同样的操作时,编译器会给我一个错误,说a
受到保护。标准对此有何规定?
错误为
prog.cpp: In member function 'void bar::copy_a_from_foo(foo&)':
prog.cpp:3:7: error: 'int foo::a' is protected
int a;
^
prog.cpp:9:11: error: within this context
a = o.a;
附言:我看了这个问题,但不太一样:我试图从派生类中访问受保护的成员。
只能通过指向派生类型对象的指针或引用来访问基类的protected
成员。
如果您更改
void copy_a_from_bar(bar& o){
a = o.a;
}
至
void copy_a_from_bar(bar& o){
foo& foo_ref = o;
a = o.a; // OK. Accessing it through `bar&`
a = foo_ref.a; // Not OK. Accessing it through `foo&`
}
你会看到同样的错误。
这个SO回答给出了为什么允许访问基类的protected
成员将是对基类成员的protected
状态的潜在破坏的指示。
假设你有:
class baz : public foo
{
void update_a(foo& f)
{
f.a = 20;
}
};
和用途:
bar x;
baz z;
z.update_a(x);
如果允许,baz
将能够更改bar
的成员的值。这不好。
protected
意味着它可以作为派生类中的成员访问。它不会授予派生类不受限制的访问权限。
推理(我想)是这样的,派生类可以修改基类型,以便维护派生类型自己的约定。但是,它不需要访问其他派生类的受保护成员,因为这可能会使的合约无效。
合同是对成员国状态的承诺。您可能熟悉的一些示例契约位于字符串的内部:size
包含缓冲区中字符串的长度,buffer[size]
包含null(这里有很多技术细节,但它们并不重要)。此外,缓冲区总是指向null或以null结尾的有效字符串,具有唯一所有权。字符串类努力确保,无论怎样,所有这些都是真的。(字符串实际上没有任何这些契约,因为它的成员是私有的,这只是一个例子)
对于protected
的含义,这是一个常见的误解。这并不意味着您可以从派生类型访问任何基类型对象的成员,而只能访问作为派生类型对象一部分的子对象。
其原理是,您可以控制对象的成员,在那里您知道自己在做什么,但不会轻易扰乱其他对象的状态。考虑这个例子,其中CachedDoubleValue
使用基础对象中值的两倍来维护缓存值:
class Base {
protected:
int x;
};
class CachedDoubleValue : public Base {
int y;
public:
void set(int value) {
x = value;
y = 2 * x;
}
};
class AnotherDerived : public Base {
public:
static void setX(Base &b, int value) {
b.x = 10;
}
};
int main() {
CachedDoubleValue a;
a.set(1); // a.x = 1, a.y = 2
AnotherDerived::modifyX(a, 10);
// Invariant broken: a.x = 10, a.y = 2; a.x != 2 * a.y
}
- 初始化指向类实例的智能指针并访问其方法
- 如何从实现接口的模板化类实例访问结构
- 访问同级类实例的成员
- 从模板参数包实例化的访问类实现
- 如何使用包含内部类的类实例有效地从内部类访问成员?
- 限制多模板参数朋友函数可访问的类实例的范围
- 从 QT Widget 对象实例访问 QT Widget 子成员
- 为什么 clang 不允许通过实例访问嵌套枚举类?
- 从C++中的父类实例访问子类方法
- 我可以从 C++ 中的派生实例访问指向基本实例的指针吗?
- c++单例类实例访问整个应用程序
- 为什么我无法从基类的实例访问受保护的成员?
- 为什么可以从派生实例访问基类中的受保护变量
- 尝试从从 DLL 加载的驱动类实例访问基类向量成员时,程序崩溃
- 通过外部类的实例访问嵌套的内部类
- 通过对象实例访问私有静态成员
- 如何在c++中从一个实例访问另一个实例的信息
- 任何实例访问(类的)所有实例
- 从子类实例访问和更改父值
- 在c++中,通过指针或实例访问类/结构的优点是什么?