bol*_*lov 0 c++ oop inheritance encapsulation
我看到它的方式,在OOP中,公共接口的一个角色是确保对象始终处于有效状态(这是您不能memcpy使用非pod类型的一个重要原因).例如,一个非常基本的,迂腐的例子:(请忽略类似java的set/get):
class Restricted {
protected:
int a;
public:
Restricted() : a{0} {}
// always returns a non-negative number
auto get() const -> int {
return a;
}
auto set(int pa) -> void {
if (pa < 0)
a = 0;
else
a = pa;
}
auto do_something() {
// here I code with the assumption that
// a is not negative
}
};
Run Code Online (Sandbox Code Playgroud)
在此示例中,类Restricted的建模方式使Restricted对象始终保持非负数.这就是我为其定义有效状态的方法Restricted.通过查看界面我可以说Restricted ::get总会返回一个非负数.用户无法Restricted持有负数.
a受保护,让选项轻松扩展类.所以让我们扩展Restricted一个允许所有数字的类型:
class Extended : public Restricted {
public:
Extended() { a = -1; }
auto set(int pa) -> void {
a = pa;
}
auto do_something() {
// now a can be negative, so I take that into account
}
};
Run Code Online (Sandbox Code Playgroud)
乍一看一切都还好.Extended不修改Restricted或它的行为.Restricted仍然是相同的,我们只是添加另一种类型,也允许负数.
除了我们最初的假设Restricted不再支持.用户可以轻松获取Restricted保存负数的对象(处于无效状态的对象),因为:
C++ 允许对象切片而不发出任何警告:
Restricted r = Extended{};
// or
Extended e;
e.set(-24);
Restricted r = e;
// and then:
r.do_something(); // oups
Run Code Online (Sandbox Code Playgroud)
有些东西没有加起来:
Extended作为子类的错误是Restricted什么?如果是这样,为什么?a为protected,如果我希望a是永远非负?为什么?protected不应允许改变我班级的行为.C++允许对象切片是错误的?如果我希望a总是非负的,那么设置为受保护是不对的?为什么?
是的,这是错的.Restricted的接口要求的是a为非负.这是该类型设置的不变量.并且它没有virtual允许派生类覆盖该不变量的函数.
由于违反(和因为你的好奇缺乏那种不变的virtual功能),Extended是打破OOP的基本规则:一个派生类的实例应该能够像(公共)基类的一个实例来对待.这并不意味着切片; 我的意思是,你应该能够传递Extended给一个带有指针/引用的函数Restricted,并且一切都应该像它正在与之交谈一样Extended.
创建Extended作为Restricted的子类是错误的吗?如果是这样,为什么?
这是错的:
使a protected代替private.
Make Restricted的界面不是virtual.
C++允许对象切片是不对的?
没有.