当前位置: 首页 > article >正文

effective c++ item35-39

item35:考虑虚函数的替代方案

NVI----Non-Virtual Interface

不使用虚函数接口,子类也可以实现按需求更改实现:
在这里插入图片描述

The Strategy Pattern via Function Pointers

也可以使用函数指针
在这里插入图片描述
或者使用stl::function
在这里插入图片描述

The “Classic” Strategy Pattern

item36:不要重新定义non-virtual函数

见https://blog.csdn.net/weixin_44609676/article/details/130382495

item37:不要重新定义重写函数的默认参数

在这里插入图片描述
可以看到,b和pb调用的是同一个虚方法,但是输出到结果却不一样。因为f是虚函数,在运行时才动态绑定需要执行的函数,但是参数却是静态绑定的,在编译期pb的参数就已经是1了。
即使把BC的默认参数都换成1,也不推荐这样做。因为会增大维护代码的成本,如果默认参数要改,全部的相关代码都要改
可以使用第35条款的NVI来解决:

class A{
private:
	virtual void f(int x) const = 0;		// 子类复写f方法,调用dof方法
public:
	void int dof(int x = 1) const{			// 非虚,不允许复写
		cout << "A" << x <<endl;
	}
}

item38:通过组合建模出has-a或实现关系

has-a关系

  • has-a:For example, consider a “Car” class that has a “Engine” class as a member variable. The Car class has-a Engine, which means that the Engine object is a part of the Car object, and it cannot exist without the Car. Similarly, the Car class may have other has-a relationships with classes such as “Wheels”, “Transmission”, “Seats”, etc.
  • is-a:For example, consider a “Vehicle” class and a “Car” class. The Car class is a specialized version of the Vehicle class, meaning that it inherits all of the attributes and behaviors of the Vehicle class, but it also has its own unique attributes and behaviors that make it different from other types of vehicles.

实现关系

在这里插入图片描述
使用list来实现set,如果用public继承,就会违反is-a的关系,因为set并不是list。就可以用包含关系来实现。

item39:EBO(空基类优化)

empty base optimization

任何对象大小至少为1(c++20:使用[[no_unique_address]])
然而,基类子对象不受此约束,而且完全可以从对象布局中优化掉
在这里插入图片描述
B的大小为8,因为内存对齐,在A a后面补上了3个字节。
C这种现象就叫EBO。
空类不一定是真的为空,也可以是包含了typedefs、enums、static、non-virtual函数等

不应用EBO的场景

如果某个非静态数据成员的类型与一个空基类的类型相同或者由该空基类派生,那么禁用空基类优化。因为要求两个同类型的基类子对象在最终派生类型的对象表示中必须拥有不同地址。
在这里插入图片描述
派生类B的内存布局是:A占一个字节,成员变量a占一个字节,然后补2个字节,int占4个字节
派生类C的内存布局是:A不占内存,int占四个字节
派生类D的内存布局是:A占一个字节,空3个字节,c、int都占4个字节
在MSVC中,有且仅有最后一个空基类应用空基类优化,其余空基类均不应用空基类优化,并分配一个字节。在GCC中,无论存在多少个空基类,均应用空基类优化,不分配任何空间,空基类地址与派生类首对象地址相同。

no_unique_address注解(C++20)

如果空成员子对象使用属性[[no_unique_address]] ,那么允许像空基类一样优化掉它们。取这种成员的地址会产生可能等于同一个对象的某个其他成员的地址。
如下面的例子,b的地址和b内成员变量的地址相同。
在这里插入图片描述
在这里插入图片描述

item39:明智的使用private继承

class A{};
class B:private A{};
void func(const A& a);
....
A a;
B b;
func(a);		// right
func(b);		// error

private只是实现上的继承,不包括接口上的继承,不是is-a的关系。A和B已经没有关系了,只是对软件实现上有意义。
当我们需要访问基类中的protected成员,或者是要复写虚函数时,可以考虑私有继承。


http://www.kler.cn/a/15648.html

相关文章:

  • 【MySQL】MySQL的笛卡尔积现象是什么?简单说说
  • windows C#-异步编程概述(二)
  • ChromeDriver 官方下载地址_测试自动化浏览器驱动
  • 微信小程序设置屏幕安全距离
  • .Net Core根据文件名称自动注入服务
  • c++原型模式(Prototype Pattern)
  • Apache Druid中Kafka配置远程代码执行漏洞(MPS-2023-6623)
  • 工厂能耗管理系统linux嵌入式边缘网关
  • 元宇宙展厅--音乐科技展厅
  • js字符串 常用方法 并带详细讲解
  • Java项目上线之云服务器环境篇(四)——Redis的安装与配置
  • 安卓开发_广播机制_发送自定义广播
  • RK3399平台开发系列讲解(LED子系统篇)LED子系统详解
  • Apache Zeppelin系列教程第一篇——安装和使用
  • springboot+nodejs+vue众筹项目管理系统平台系统
  • VUE入门神器
  • jvm调优策略
  • 牛客网Python入门103题练习|【07--循环语句(1)】
  • C语言入门篇——指针篇
  • ddp pytoch多卡分布式训练
  • Vue3之setup参数介绍
  • Java学习过程(韩顺平661-665)
  • 浅谈测试用例设计 | 京东云技术团队
  • 【HQL - 查询用户的累计消费金额及VIP等级】
  • 霍兰德人格分析雷达图
  • 【Qt】根据界面所在显示器自适应调整ui大小