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

时间:2011-06-07 11:05:28

标签: c++ inheritance

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访问权限的尝试?

3 个答案:

答案 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
}

会发生什么?

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

正如您所注意到的那样,cf.length缓存3长度的不变量因为length通过string无法保护访问而被破坏。