软件框架-无绪开发2

1. 工厂方法优于构造函数<使用工厂方法代替构造函数>

优点: 
(1)工厂方法返回值并不一定是声明类型的实例,可以是它的子类实例
代码更加简洁。
------(更好体现多态)
(2)每次返回的对象也并不一定都是新创建的对象,完全可以将其缓存。相比每次调用构造函数都创建一个实例,而工厂方法可以缓存以前创建的对象,并重用它们,节省内存。
(3)对同步的控制,在工厂方法中可以将创建对象前后的相应代码进行统一处理;构造函数对于这种情况就无能为力了
(4)工厂方法支持参数化的返回类型,但构造函数是做不到这一点的
(5)工厂方法是一个方法,一个方法并不会限定返回值实例的类型,可以是类,也可以是接口;但构造函数的返回值却一定是指定的实例。

2.让所有内容都不可更改

设计的类如果不考虑让其拥有子类,就应该让这个类不能被继承
(1)private修饰
(2)转换,使用工厂方法
(3)final修饰,强制外部无法继承此类
#include <iostream>
using namespace std;

template <typename T>
class Base{
    friend T;
private:
    Base(){
        cout << "base" << endl;
    }
    ~Base(){}
};

class B:virtual public Base<B>{   //一定注意 必须是虚继承
public:
    B(){
        cout << "B" << endl;
    }
};

class C:public B{
public:
    C(){}     //继承时报错,无法通过编译
};


int main(){
    B b;      //B类无法被继承
    //C c;
    return 0;
}
类Base的构造函数和析构函数因为是私有的,只有Base类的友元可以访问,B类在继承时将模板的参数设置为了B类,所以构造B类对象时们可以直接访问父类(Base)的构造函数。
为什么必须是虚继承(virtual)呢?
参见 c++Primer 4th 第17.3.7节 特殊的初始化语义
通常每个类只初始化自己的直接基类,但是在虚继承的时候这个情况发生了变化,可能导致虚基类被多次初始化,这显然不是我们想要的。(例2: AA,AB都是类A的派生类,然后类C又继承自AA和AB,如果按之前的方法会导致C里面A被初始化两次,也会存在两份数据)
为了解决重复初始化的问题,从具有虚基类的类继承的类在初始化时进行了特殊处理,在虚派生中,由最低层次的派生类的构造函数初始化虚基类。在我们上面的例1中就是由C的构造函数控制如何进行虚基类的初始化。
为什么B类不能被继承?
回到例1,因为B是Base的友元,所以B对象可以正常创建,但由于B使用了虚继承,所以如果要创建C对象,那么C类的构造函数就要负责虚基类(Base)的构造,但是Base的构造函数是私有的,C没有访问的权限(ps:友元关系不能被继承的),所以例1中的C类在编译时就会报错。这样B类就不能被继承了。

C++11 

  1. #include "stdafx.h"  
  2. #include <iostream>  
  3.   
  4. // 标示符含义:  
  5. // override,表示此虚函数必定“重写”了基类中的对应虚函数。  
  6. // final,(1)作用在虚函数:表示此虚函数已处在“最终”状态,后代类必定不能重写这个虚函数。  
  7. //        (2)作用在类:表示此类必定不能被继承  
  8. // 编译器将帮你检查是否“必定”  
  9.   
  10. class B1 final {}; // 此类不能被继承  
  11. // class D1: public B1 {}; // error!  
  12.   
  13. class B  
  14. {  
  15. public:  
  16. //  virtual void func() override // error! 指定了重写但实际并没重写,没有基类  
  17. //  {   
  18. //      std::cout << __FUNCTION__ << std::endl;  
  19. //  }  
  20.     virtual void f() const   
  21.     {   
  22.         std::cout << __FUNCTION__ << std::endl;  
  23.     }  
  24.     virtual void fun()   
  25.     {   
  26.         std::cout << __FUNCTION__ << std::endl;   
  27.     }  
  28. };  
  29.   
  30. class D : public B  
  31. {  
  32. public:  
  33.     virtual void f(int)      // ok! 隐藏,由于没有重写同名函数B::f,在D中变为不可见  
  34.     {   
  35.         std::cout << "hiding: " <<__FUNCTION__ << std::endl;   
  36.     }   
  37. //  virtual void f() override   // error! 指定了重写但实际并没重写,类型声明不完全相同  
  38. //  {   
  39. //      std::cout << __FUNCTION__ << std::endl;   
  40. //  }   
  41.     virtual void fun() override final // ok! 指定了重写实际上也重写了,同时,指定为最终,后代类中不能再重写此虚函数  
  42.     {   
  43.         std::cout << __FUNCTION__ << std::endl;   
  44.     }   
  45. };  
  46.   
  47. class D2 : public D  
  48. {  
  49. public:  
  50.     virtual void f() const      // ok! 重写B::f(),同时,由于没有重写D::f(int),在D2中变不可见  
  51.     {   
  52.         std::cout << __FUNCTION__ << std::endl;  
  53.     }  
  54. //  virtual void fun() // error! 基类的此虚函数被指定为最终,不能被重写,虽然没有显示指定"override"  
  55. //  {  
  56. //      std::cout << __FUNCTION__ << std::endl;  
  57. //  }  
  58. //  virtual void fun() override // error! 基类的此虚函数被指定为最终,不能被重写  
  59. //  {  
  60. //      std::cout << __FUNCTION__ << std::endl;  
  61. //  }   
  62. };  
  63.   
  64. int _tmain(int argc, _TCHAR* argv[])  
  65. {  
  66.     D2 d2;  
  67.     D d1;  
  68.     B *b = &d1;  
  69.     b->f();      // B::f  
  70.     b->fun();    // D::fun  
  71. //  d1.f();     // error! B::f在D中不可见  
  72.     d1.f(10);   // hiding: D::f  
  73. //  d2.f(10);   // error! D::f(int)在D2中不可见  
  74.     d2.f();     // D2::f  
  75.     d2.fun();   // D::fun  
  76.   
  77.     return 0;  
  78. }  

3.避免滥用setter方法

4.方法优于字段

5.尽可能用namespace来公开功能

6.赋予对象创建者更多权利

7.避免暴露深层次的继承

继承只是增加功能,尽量不重写功能



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yongwuzhijing800

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值