在 The C ++ Programming Language 一书的第24.3.4章中,它说
class Cfield : public Field{ /*...*/ }
这表达了a的概念
Cfield
真的是一种场, 允许符号方便的时候 编写使用a的Cfield
函数 该领域的成员Cfield
, - 最重要的是 - 允许Cfield
覆盖Field 虚函数。 障碍就是这样Cfield*
到Field*
次转化Cfield
的声明中隐含的 击败所有控制访问的企图 到Field
:void g(Cfield* p) { *p = "asdf"; // access to Field controlled by Cfield's assignment operator: // p->Cfield::operator=("asdf") Field* q = p; // implicit Cfield* to Field* conversion *q = "asdf" // OOPS! no control }
我在这里不明白,是粗体句。 Cfield
如何击败控制Field
访问权限的尝试?
实际上,代码的最后一行是:
*q = "asdf";
会致电Field::operator=("asdf")
,那么Cfield
如何击败控制Field
访问权限的尝试?
答案 0 :(得分:4)
CField
个实例应该提供对CField::operator=()
基类数据的受控制(即以某种方式检查Field
}。但是,如果您隐式地将CField *
强制转换为Field *
,然后取消引用它,那么该控件就会消失,因为您选择了Field::operator=()
。
我同意这不是BS最清楚的着作,在我看来有点无问题 - 如果你把它放在心上,你总能得到“不受控制的访问”。
答案 1 :(得分:2)
我想它指的是Cfield
的赋值运算符可能会执行保持对象状态一致所需的特殊事情的问题。通过使用超类的赋值运算符,不变量可能会被破坏。
答案 2 :(得分:1)
让我们举一个具体的例子:
struct Field {
Field(char const* s): string(s) {}
char const* string;
};
struct CField: Field {
CField(char const* s): Field(s), length(s ? ::strlen(s) : 0) {}
std::size_t length;
};
这是一种非常基本的字符串,不允许修改它所引用的字符串。 CField
通过缓存字符串的长度来扩充Field
类。
现在,在行动中:
void foo(CField& cf) { // 0
cf = "foo"; // 1
Field& f = cf; // 2
f = "foobar"; // 3
}
会发生什么?
CField& CField::operator=(CField const&)
,创建一个临时CField
(使用构造函数),cf.string
为"foo"
,cf.length
为{{1 }} 3
访问Field
,创建临时Field& Field::operator=(Field const&)
(使用构造函数),Field
为cf.string
,"foobar"
为{{1 (未更改)正如您所注意到的那样,cf.length
缓存3
长度的不变量因为length
通过string
无法保护访问而被破坏。