C++ 设计模式:工厂方法(Factory Method)
工厂方法(Factory Method)
工厂方法是一种创建型设计模式,其在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型。
问题
在面向对象系统设计中经常可以遇到以下的两类问题:
1.我们经常会抽象出一些类的公共接口以形成抽象基类或者接口。这样我们可以通过声明一个指向基类的指针来指向实际的子类实现,达到了多态的目的。所以就不得不在要用到子类的地方写new 对象。这样实体类的使用者必须知道实际的子类名称,以及会使程序的扩展性和维护变得越来越困难。
2.还有一种情况就是在父类中并不知道具体要实例化哪一个具体的子类。只能在父类中写方法调用,具体调用哪一个类的方法交给子类实现。
以上两个问题也就引出了 Factory 模式的两个最重要的功能:
1)定义创建对象的接口,封装了对象的创建。
2)使得具体化类的工作延迟到了子类中。
C++ 设计模式
创建型模式
创建型模式提供了创建对象的机制,能够提升已有代码的灵活性和可复用性。
工厂方法(Factory Method)
工厂方法是一种创建型设计模式,其在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型。
C++ 设计模式:工厂方法(Factory Method)
抽象工厂(Abstract Factory)
抽象工厂是一种创建型设计模式,它能创建一系列相关的对象,而无需指定其具体类。
Post not found: C++/C++DesignPatterns/
生成器(Builder)
生成器是一种创建型设计模式,使你能够分步骤创建复杂对象。该模式允许你使用相同的创建代码生成不同类型和形式的对象。
Post not found: C++/C++DesignPatterns/
原型(Prototype)
原型是一种创建型设计模式,使你能够复制已有对象,而无需使代码以来它们所属的类。
Post not found: C++/C++DesignPatterns/
单例(Singleton)
单例是一种创建型设计模式,让你能够保证一个类只有一个 ...
C++ 11:thread-local storage(线程局部存储)
存储期
程序中的所有对象都具有下列存储期之一:
自动(automatic)存储期。这类对象的存储在外围代码块开始时分配,并在结束时解分配。未声明为 static、extern 或 thread_local 的所有局部对象均拥有此存储期。
静态(static)存储期。这类对象的存储在程序开始时分配,并在程序结束时解分配。这类对象只存在一个实例。所有在命名空间(包含全局命名空间)作用域声明的对象,加上声明带有 static 或 extern 的对象均拥有此存储期。有关拥有此存储期的对象的初始化的细节,见非局部变量与静态局部变量。
线程(thread)存储期。这类对象的存储在线程开始时分配,并在线程结束时解分配。每个线程拥有它自身的对象实例。只有声明为 thread_local 的对象拥有此存储期。thread_local 能与 static 或 extern 一同出现,它们用于调整链接。关于具有此存储期的对象的初始化的细节,见非局部变量和静态局部变量。
动态(dynamic)存储期。这类对象的存储是通过使用动态内存分配函数来按请求进行分配和解分配的。
子对象和引用成员的存储期与它们的完整对 ...
C++ 11:GC interface (removed in C++23)(GC 接口)
GC interface (removed in C++23)
C++ 11:range-for
基于范围的 for 循环
在一个范围上执行 for 循环。
用作对范围中的各个值(如容器中的所有元素)进行操作的传统 for 循环的更加可读的等价版本。
语法
属性(可选) for ( 初始化语句(可选)范围变量声明 : 范围表达式 ) 循环语句
注意,所有 初始化语句 必然以分号 ; 结尾,因此它经常被非正式地描述为后随分号的表达式或声明。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566// 示例#include <iostream>#include <vector> int main(){ std::vector<int> v = {0, 1, 2, 3, 4, 5}; for (const int& i : v) // 以 const 引用访问 std::cout << ...
C++ 11:static_assert
进行编译时断言检查。
语法
static_assert ( 布尔常量表达式 , 消息 )
如果 布尔常量表达式 返回 true,那么该声明没有效果。否则将发布编译时错误,且当存在 消息时诊断消息中会包含其文本。
消息 可以省略。
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849// 示例#include <type_traits> template <class T>void swap(T& a, T& b) noexcept{ static_assert(std::is_copy_constructible<T>::value, "交换需要可复制"); static_assert(std::is_nothrow_copy_constructible<T>::value && ...
C++ 11:multithreaded memory model (多线程内存模型)
多线程内存模型
为 C++ 抽象机的目的定义了计算机内存存储的语义。
可为 C++ 程序所用的内存是一或多个字节的连续序列。内存中的每个字节拥有唯一的地址。
字节(byte)是最小的可寻址内存单元。它被定义为相接的位序列,其大到足以保有任何 UTF-8 编码单元(256 个相异值)
与 C 相似,C++ 也支持 8 位或更大的字节。
char、unsigned char 和 signed char 类型把一个字节用于存储和值表示。字节中的位数可作为 CHAR_BIT 或 std::numeric_limits::digits 访问。
内存位置
一个内存位置是
一个标量类型(算术类型、指针类型、枚举类型或 std::nullptr_t)对象
或非零长位域的最大相接序列
注意:语言的各种功能特性,例如引用和虚函数,可能涉及到程序不可访问,但为实现所管理的额外内存位置。
12345678910struct S { char a; // 内存位置 #1 int b : 5; // 内存位置 #2 int c : 11, // 内存位置 #2 (延续) ...
C++ 11:alignof 与 alignas
alignof 运算符
查询类型的对齐要求。
语法
alignof( 类型标识 )
返回 std::size_t 类型的值。
返回由类型标识所指示的类型的任何实例所要求的对齐字节数,该类型可以是完整对象类型、元素类型完整的数组类型或者到这些类型之一的引用类型。
如果类型是引用类型,那么运算符返回被引用类型的对齐要求;如果类型是数组类型,那么返回元素类型的对齐要求。
1234567891011121314151617181920212223242526272829303132333435363738394041// 示例#include <iostream> struct Foo{ int i; float f; char c;}; // 注:下面的 `alignas(alignof(long double))`// 如果需要可以简化为 `alignas(long double)`struct alignas(alignof(long double)) Foo2{ // Foo2 成员的定义...}; s ...
C++ 11:noexcept
noexcept
noexcept 说明符
指定函数是否抛出异常。
语法
说明
noexcept
与 noexcept(true) 相同
noexcept(表达式)
如果 表达式 求值为 true,那么声明函数不会抛出任何异常。后随 noexcept 的 ( 只能是该形式的一部分(它不是初始化器的开始)。
noexcept 说明不是函数类型的一部分(正如同动态异常说明),而且只能在声明函数、变量、函数类型的非静态数据成员、函数指针、函数引用或成员函数指针时,以及在以上这些声明中声明类型为函数指针或函数引用的形参或返回类型时,作为 lambda 声明符或顶层函数声明符的一部分出现。它不能在 typedef 或类型别名声明中出现。
C++ 中的每个函数要么不会抛出,要么有可能会抛出。
有可能会抛出的函数是:
声明带有求值为 false 的 表达式 的 noexcept 说明符的函数
声明不带有 noexcept 声明的函数,除了
析构函数,除非有任何可能在构造的基类或成员的析构函数有可能会抛出
隐式声明的或在它的首个声明被预置的默认构造函数、复制构造函数、移动构 ...
C++ 11:lambda expressions(lambda 表达式)
lambda expressions(lambda 表达式)
语法:
capturemutable->return-type{ statement; };
[capture] 捕获列表。
[parameters] 参数列表。
->return-type 返回类型。
{statement} 函数体。
语法上,捕获列表由多个捕获项组成,并以逗号分割,形式如下(值传递和引用传递):
1.[var] 表示值传递方式捕获变量var
2.[=] 表示值传递方式捕获所有父作用域的变量(包括this)
3.[&var] 表示引用传递捕获变量var
4.[&] 表示引用传递不会所有父作用域的变量(包括this)
5.[this] 表示值传递方式捕获当前的this指针
父作用域:指的是包含lambda函数的语句块。
123456789101112131415161718#include <iostream>using namespace std;int main(){ int a = 2, b = 4; auto ...