原型模式
用原型实例指定创建对象的种类,并且通过拷贝原型创建新的对象,防止浅拷贝的发生,由被拷贝对象控制拷贝行为。
功能类似于拷贝构造,拷贝构造的调用由程序自动调用。而原型模式的Clone由被拷贝对象调用。完成对象实例的自拷贝。在大话设计模式中:
A a;
A b = a;
A c = b;
在某些语言中,b和c被认为是a的引用。与a公用一个内存实例。在c++中这被优化为使用拷贝构造来生成新对象。
为了抽象出自拷贝的特性,抽奖出接口类Prototype,包含Clone函数。
#ifndef _DESIGN_PATTERN_PROTOTYPE_PROTOTYPE_HPP_
#define _DESIGN_PATTERN_PROTOTYPE_PROTOTYPE_HPP_
namespace design_pattern
{
class Prototype
{
public:
virtual Prototype *Clone()const = 0;
};
class ConcretePrototype : public Prototype
{
public:
ConcretePrototype() {}
ConcretePrototype(ConcretePrototype const &b) {}
Prototype* Clone() const
{
return new ConcretePrototype(*this);
}
};
}
#endif // !_DESIGN_PATTERN_PROTOTYPE_PROTOTYPE_HPP_
//Prototype_main.cpp
#include <iostream>
#include <memory>
#include "prototype.hpp"
using design_pattern::Prototype;
using design_pattern::ConcretePrototype;
using std::unique_ptr;
using std::make_unique;
using std::cout;
using std::endl;
int main()
{
ConcretePrototype c;
Prototype * prot = &c;
unique_ptr<Prototype *> prot1 = make_unique<Prototype *>(prot->Clone());
cout << "proto: " << &prot << " clone proto: " << prot1.get() << endl;
return 0;
}
语法tips
C/C+±-动态弱类型语言:
- 动态/静态类型语言–类型检查阶段
- 静态类型语言:在编译器进行类型检查,定义时需明确写出变量类型。C, Java
- 动态类型语言:在运行时进行类型检查,定义时不强制要求明确变量类型。Python
- 强类型/弱类型语言–是否允许隐式类型转换
- 强类型语言:数据类型一旦定义,若非经过显示类型强转,类型不变。Python
- 弱类型语言:数据类型可以隐式转换。C/C++
C++四种cast:
-
dynamic_cast<> 允许RTTI类型转换,完成派生类到基类的类型转换
-
static_cast<> 类似C的强制类型转换
double <- float ^ | long ^ | unsigned ^ | int <- char, short
-
const_cast<> 取消const属性的类型转换
-
reinterpret_cast<>:对对象内存重新解释
与static_cast<>的区别在于对继承情况下的类型转换:
class A { virtual void func(){}}; class C : public A {}; //Class mem layout // 0 - C: // 0 - A: vfptr // 4 - --- // B: //
unique_ptr vs scoped_ptr:
- std::unique_ptr 可转移所有权,boost::scoprd_ptr 不可转移
- unique_ptr的构造需make_unique模版函数
- make_unique不能进行实参推演
- unique_ptr模版实参使用实体类型。不带指针*.
NULL vs nullptr
- NULL的定义:
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
-
NULL 在cplusplus中时整型常量0,不带有指针语义。在cplusplus中的模板匹配中会出现问题。
-
而nullptr则具有通用指针的语义。
-
OPPO d; Brand *ptr = &d; 与 Brand *ptr = &OPPO();
语法上可行,后者运行时不调用OPPO构造函数。
由于Brand中存在纯虚函数,在虚函数表中纯虚函数使用_purecall填充。编译时不出错,运行时引发调用Abort()