关于C++编程语言的问题

Question About The C++ Programming Language

本文关键字:问题 编程语言 C++ 关于      更新时间:2023-10-16

《C++编程语言》一书的第24.3.4章中说:

class Cfield : public Field{ /*...*/ }

这表达了一个概念,即 Cfield真的是一种场, 允许在以下情况下使用符号方便 编写Cfield使用 现场部分的成员 Cfield,最重要的是 - 允许Cfield覆盖字段 虚拟功能。障碍在于 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的访问的尝试的呢?

>CField实例应该提供对Field基类数据的受控(即通过CField::operator=()以某种方式检查(访问。但是,如果您隐式地将CField *投射到Field *,然后取消引用它,则该控件将消失,因为您拾取了Field::operator=()

我同意这不是 BS 最清晰的著作,在我看来有点无关紧要——如果你下定决心,你总是可以"不受控制地访问"任何东西。

我想它指的是Cfield的赋值运算符可能会做保持对象状态一致所需的特殊操作的问题。通过使用超类的赋值运算符,可能会破坏不变量。

让我们举一个具体的例子:

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
}

会发生什么?

  • 第 0 行:状态未知
  • 第 1 行:调用 CField& CField::operator=(CField const&) ,这将创建一个临时CField(使用构造函数(,cf.string "foo"cf.length 3
  • 第 2 行:同一对象,可通过Field直接访问
  • 第 3 行:调用 Field& Field::operator=(Field const&) ,这将创建一个临时Field(使用构造函数(,cf.string "foobar" cf.length 3(未更改(

如您所注意的,由于通过 Field&string进行不受保护的访问,length缓存string长度的不变性被破坏。