c++ - 对象设计的抽象

标签 c++

如果我们只在父类(super class)中使用 protected 和 private 访问修饰符,继承如何破坏封装?

有时声称继承公开父类(super class)实现。如果成员变量被声明为私有(private),这肯定不是真的吗?如果这是指在父类(super class)中所做的更改会破坏子类,这不会影响非继承吗?

在公开底层实现方面,我也看不出组合有何不同?我们只能使用组合方法来使用公共(public)函数——这肯定会暴露更多吗?

最佳答案

派生类可以访问基类的部分实现。例如。如果您对基类中的任何或所有成员使用 protected,那么基类将无法强制执行它自己的不变量。这可能会破坏基类的功能。更改字段名称或删除或添加字段名称可能会导致派生类出现问题,除非它们是私有(private)的,因此再次公开实现可能会破坏原本正确的代码。

模板模式是一种故意暴露基类部分实现的方式,它是故意的并不意味着它不暴露(部分)实现。使用组合(策略)来获得相同的结果(通常与开放/封闭原则相关)具有更松散的耦合。 例如。如果您更改其中一个虚拟方法的签名(例如名称)或添加在模板模式中使用的新(抽象)方法,将级联更改为所有派生类。在组合的情况下,您可以更改进行组合的类中所有方法的名称,而无需更改您组合的任何类。您还可以在不更改其他类的情况下向算法添加另一个步骤(只要您组成的部分之一已经支持此功能)

另一种看待为什么虚拟方法会破坏封装的方式:

上这门课

class ArrayPrinter{
   private bool CanContinue<T>(T[] array, int newIndex){
      return newIndex<array.Length;
   }

   public void Print<T>(T[] array){
      for(var i = 0;CanContinue(array,i);i++){
         Console.WriteLine(string.Format("{0}",array[i]);
      }
   }
}

在上面的示例中,我们可以确定 Print 的实现不会导致索引越界(线程安全除外),并且数组的所有元素都将被打印(除非 Console.WriteLine 或 string.Fromat 失败).但是,如果我们将 CanContinue 的签名更改为以下内容

   protected virtual bool CanContinue<T>(t[] array, int newIndex)

ArrayPrinter 将正常工作不再有任何保证。我们已经可以从类的外部更改 Print 的实现,因此破坏了封装。有些人可能会争辩说,如果你公开你的领域,你只会破坏封装。我不同意下面的代码遇到与上面完全相同的问题,尽管它公开了一个字段(通过一个属性,只是为了表明隐藏你是属性后面的字段并不能确保你没有封装破损)

class ArrayPrinter<T>{
   private Func<T[],int,bool> _canContinue;
   protected Func<T[],int,bool> CanContinue{
           get{
               return _canContinue ?? canContinue;
           }
           set{
                _canContinue = value;
           }
   }
   private bool canContinue(T[] array, int newIndex){
      return newIndex<array.Length;
   }

   public void Print<T>(T[] array){
      for(var i = 0;CanContinue(array,i);i++){
         Console.WriteLine(string.Format("{0}",array[i]);
      }
   }
}

关于c++ - 对象设计的抽象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9463966/

相关文章:

c++ - 确保模板化泛型参数的返回类型

c++查找字符串中存在的元素的 vector

c++ - 将派生指针隐式转换为其相应基址的引用

C++ boost json ptree 解析器无法解析字符串

c++ - 转换和积累

c++ - 如何将具有一定数量单词的 vector<string> 的输出读取到一行?

c++ - 对 2 个整数执行 XNOR

c++ - Asio同步IPv6 UDP服务器

c++ - 动态地将顶点发送到着色器? (没有 glGenBuffers)Opengl

c++ - 在 C++ 中调试函数参数的值