首页 > 编程语言 >C++_默认构造函数和重载以及设计模式

C++_默认构造函数和重载以及设计模式

时间:2024-12-09 17:10:04浏览次数:10  
标签:函数 -- 模式 运算符 对象 C++ 重载 设计模式 构造函数

类和类之间关系

类外:  静态变量,是在编译阶段就分配好空间,对象还没创建的时候就有了空间

类:类-对象-对象是类的一个实例
   类头(class head)和类体(class body)。 将数据和行为封装在单个单元中--封装
    成员变量  成员函数 成员变量称为属性(property);成员函数称为方法(method)
	   静态成员变量 在内存中只有一个副本,为所有类的实例共享。
          静态成员变量必须在类中声明,类外定义。声明时使用关键字static ,定义的时候不用加static	
       静态成员函数: 属于类不属于对象,静态函数能操作静态数据,不能操作非静态数据	  
	   共享(static),又要实现不能修改(const),static前面加上const,
	成员函数的--参数和局部变量 
    成员函数--其他类的静态方法
    成员变量--引用其他类的全局变量 其他类的属性  其他类的实例-其他类的对象		
	  
	空类:  
       在空类情况下编译器会自动生成以下6个默认成员函数。
  
亲疏远近
       类之间的关系强弱顺序是这样的:继承(泛化) > 组合 > 聚合 > 关联 > 依赖。
关系:  
    继承--泛化关系 is a  Generalization   
	实现--Realization
	    虚函数    中使用的关键词是 virtual    :虚函数是在基类中声明为虚函数的函数,可以有默认实现,在基类中有默认的实现,但也可以被子类重写
		纯虚函数 定义纯虚函数的语法是在函数声明后面加上 “= 0” 基类中声明但是没有定义的虚函数,它的定义留给了派生类
		如果类中存在纯虚函数,则这个类被称为抽象类,抽象类不能被实例化
	    C++通过 虚函数(Virtual Function) 实现运行时多态性	
        函数的重写:  派生类中重新定义基类--方法具有相同的函数名-相同的参数列表--相同的返回值类型	
           重写是在派生类中重新定义虚函数,函数签名必须与基类中的虚函数一致		
    组合关系 contains a   组合(Composition) 同生共死 的关系 
    聚合关系 has a 
    关联(Assocition) 
    依赖关系 use a

C++ 重载(Overloading)

     在同一个作用域内声明多个同名的函数或运算符
    重载函数 
        
		const修饰类成员函数,实际限制的是*this,表明该成员函数不能对类的任何成员进行修改
		const对象只能调用不会修改数据成员的const方法
		 运算符重载 :返回值类型 operator操作符(参数列表)
		
    重载运算符--新的运算符行为	--不能改变运算符的优先级和结合性 运算对象数量和格式不能改变  不能发明新的运算符	
	      有两个方法,第一种就是在类内部写成员函数实现,
		              第二种全局函数实现,两个方法都有一个功能的函数名称
		以加号为例:
					  operator+(), 这个函数名称是固定
		    全局函数重载+号运算符  Person p3 = operator+(p1,p2);我们习惯简写成 p3 = p1 + p2 的代码形式
			成员函数重载+号运算符  Person p3 = p1.operator+(p2);我们习惯简写成 p3 = p1 + p2 的代码形式
	 说明: 运算符是不能重载  只能重载成全局函数的运算符   只能重载成成员函数的运算符
	 
	左值与右值(Lvalue/Rvalue) 
	     同类对象之间可以通过赋值运算符“=”互相赋值 如果没有经过重载相当于值的拷贝, 称为“浅拷贝”。
	    左值可以取地址、位于等号左边;而右值没法取地址,位于等号右边。
    左值引用和右值引用
        传统的C++引用,即是左值引用		
	    右值引用:
            右值引用使用 && 符号来声明,表示对右值的引用
			右值不具名,只能通过引用的方式找到
	std::move(),它可以将一个左值强制转换为右值引用  
	
	移动语义
	    对象的所有权转移 左值对象转换为右值对象,使得后续的操作可以使用移动语义而非拷贝语义
	    
	
 运算符重载原型 函数原型:返回值类型 operator操作符(参数列表)
	
	传输值(拷贝和移动  copy and move ) 使用了相同的符号--将左值和右值的处理分离开来,左值-拷贝赋值和拷贝构造  右值-移动赋值和移动构造
	拷贝操作
	  X(const X&)
	  X& operator=(const X&)
	移动操作 
	  X(X &&)
	  X& operator=(X&&)
	构造和析构
	  X()  ~X()
    
    取地址及const取地址操作符		
        X* operator&()
        const X* operator&() const
    C++运算符 
	    * 指针运算符
        & 取地址符 返回操作数的内存地址 
		* 是一元运算符,返回操作数所指定地址的变量的值
        & 引用运算符  数据类型与变量名称的中间。

       形参实际是重新在栈申请了变量空间,增大了内存开销,而引用可以理解为替换符,并没有申请多余的变量空间。


    std::forwad() 相应实参是左值,则被转发为左值;同理如果相应实参为右值,则被转换为右值。		   

默认引入

C编译器
      C 语言标准--  main函数:程序的默认入口点 在大多数情况下,main函数是C程序的入口点
     非标准操作--  借助编译器特性和链接器选项,我们可以指定其他函数作为程序的入口
	   还可以通过链接脚本(linker script)来控制程序的入口点

C++ 编译器会自动生成以下6个默认成员函数。
     哪些:    默认的 构造函数、析构函数、
               默认重载取址运算符函数   默认重载取址运算符函数const函数
			   拷贝构造函数、以及默认重载赋值运算符函数
               默认移动构造函数(c++11)    默认重载移动赋值操作符函数(c++11)
			   
			         C++默认拷贝构造函数执行的是浅拷贝操作
                     = ,但移动构造函数是构造了一个新对象,移动赋值运算符是对已存在的对象赋值
       拷贝,然后再销毁临时对象的资源
	    即将被销毁的对象移动到接收对象,而不是复制
		std::move()用于将左值转换为右值引用,允许资源的有效转移	
            std::move()是一个标准模板函数,它可以将一个左值转换为一个右值引用,从而触发移动语义。
			std::move()并不真正移动任何东西,只是改变了对象的类型			
	 
   什么时候:  默认构造函数“被需要”的时候编译器才会帮我们合成
   充要条件,必要不充分条件
   
     如果没有经过重载,“=” 的作用就是将赋值号右侧对象的值 
	    重载赋值操作会将对象的成员变量逐个复制到另一个对象中--深拷贝”
	 内存拷贝是指将一段内存中的数据复制到另一段内存中。通常使用内存拷贝函数如memcpy()或std::copy()来实现

    std::forward()

 默认引入-无需显式地导入
      Rust -默认引入std库--CORE库、ALLOC库 STD库
      Cangjie  默认引入 core   std.core 包不需要显式导入,默认导入  core 包是标准库的核心包,提供了适用仓颉语言编程最基本的一些 API 能力
      Java 默认引入的 java.lang	     
	  Python 默认引入 __built_in__ __main__     

继承-封装-多态

  面向对象设计(Object-Oriented Design)--源代码依赖关系-以对象为手段来对源代码中的依赖关系进行控制的能力
     封装 特性其实并不是面向对象编程所独有的。其实,c 语言也支持完整的封装
	      C++通过在编程语言层面引入 public、private、protected 这些关键词,部分维护了封装性
     继承 的主要作用是让我们可以在某个作用域内对外部定义的某一组变量与函数进行覆盖。这事实上也是 c 程序员早在面向对象编程语言发明之前就一直在做的事
	     C++的继承-便利和易用
	 多态: 例如:UNIX 操作系统强制要求每个 IO 设备都要提供 open、close、read、write 和 seek 这 5 个标准函数,多态其实不过就是函数指针的一种应用
	      C++中,类中的每个虚函数(virtual function),让多态变得更安全和便于使用
     面向对象编程 其实是对程序间接控制权的转移进行了约束。插件式架构就 allows the plugin architecture to be used anywhere, for anything.
类定义:将数据和行为封装在单个单元中--封装	
  定义和使用其他类
  类(class)中的公共函数和私有成员变量
 
类--继承
      C++11标准引入final说明符它告诉编译器该虚函数不能被派生类重写

多态:C++的多态性体现在两个方面:运行时多态和编译时多态
      通过继承、虚函数和运算符重载等方式实现
    重写(override) 	
	
	而重载是在同一作用域内定义多个函数,函数名和返回值类型一致但 函数的签名不一致。
	重载(overload
    C++通过 函数重载(Function Overloading) 和 模板(Template) 实现编译时多态性 
	     重载 指的是在同一作用域内函数的函数名不变,可以有变化的是函数的参数列表,
		       具体指的是参数列中的参数数量、参数类型和参数的顺序可以变换。
		 模板是一种通用的编程机制,可以根据所传递的类型参数来生成特定的函数或类。函数模板和类模板 template
	C++通过 虚函数(Virtual Function) 实现运行时多态性--重写(override)的意思更接近覆盖
	   override说明符,这个说明符必须放到虚函数的尾部,它明确告诉编译器这个虚函数需要覆盖基类的虚函数

继承--泛化关系 is a  Generalization
    继承与派生是同一个过程的两种描述方式。 
     从子类角度,由父类继承;从父类角度,子类是派生出的
关联关系:聚合和组合的最关键区别是两个对象的生命周期是否一致,而不是出现的形式
	组合关系 contains a   组合(Composition) 同生共死 的关系
	      被组合的对象 在 组合对象创建的 同时或者创建之后 创建,在组合对象销毁之前销毁
    聚合关系 has a 
	
    关联(Assocition) 
	     单向关联、双向关联、自关联将一个类的对象 作为 另一个类的成员变量。

	依赖关系 use a 依赖(Dependency)关系是一种 使用关系
	    大多数情况下依赖关系体现在某个类的方法 使用 另一个类的对象 作为参数。
  
(一)依赖:
1. 概念:是一种使用关系,耦合度最弱。
    类A使用类B的一部分属性和方法,不会主动改变类B的内容,但是类B的变化会影响到A。
    具有偶然性、临时性。

2. 体现:
    类B 作为 类A的 成员函数参数。
    类B 作为 类A的 成员函数的局部变量
    类A的成员函数调用的 类B的静态方法
3. 代码:
  
  
被关联类B 以类的属性形式出来在关联类A中。
关联类A  引用了一个类型为被关联类B的全局变量。 

设计模式

 底层设计信息和顶层架构设计共同组成了整个房屋的架构文档,满足构建和维护该系统的需求
   The only way to go fast, is to go well.
OCP,Open For Extension Closed For Modification Principle,简称开闭原则。开闭原则是指软件实体是可以扩展的,但是不可修改 
         	模块和函数是对扩展(提供方)开放的,对修改(使用方)关闭的  
SRP,Single Responsibility Principle,单一职责原则   
DIP,Dependence Inversion Principle,依赖倒置原则。抽象不应该依赖于细节,细节应该依赖于抽象
ISP,Interface Segegation Principle,接口隔离原则。一个接口对外只提供一种功能,不同功能应该通过不同的接口提供,而不是把多种功能都封装到一个接口中
LSP,Liskov Substitution Principle,里氏替换原则。任何地方出现的抽象类,都可以使用该抽象类的实现类来代替,
CARP,Composite/Aggregate Reuse Principle,优先使用对象组合而不是继承原则
LOD,Law of Demeter,迪米特法则,也叫做最少知道原则(The Least Knowledge Principle

设计模式---经验
    第一类是创建型模式 ,该模式通常和对象的创建有关,涉及到对象实例化的方式
       单例模式、工厂模式、抽象工厂模式、建造者模式、原型模式五种;
	第二类是结构型模式,结构型模式描述的是如何组合类和对象来获得更大的结构
	    代理模式、装饰者模式、适配器模式、桥接模式、组合模式、外观模式、享元模式共7种模式。
    第三种是行为型模式,用来描述对类或对象怎样交互和怎样分配职责
        模板模式、命令模式、责任链模式、策略模式、中介者模式、
		观察者模式、备忘录模式、访问者模式、状态模式、解释器模式、迭代器模式11种模式。
创建型模式主要是将系统所需要的用到的具体类封装起来,在内部实现这些具体类的创建和结合,并对外隐藏这个过程细节		
    Prototype Pattern,原型模式是一种对象创建型模式,它采取复制原型对象的方法来创建对象的实例		
    		深拷贝浅拷贝问题
    单例模式: 一个类只能创建一个实例对象
                    (禁止类的外部访问构造函数 解决办法就是把构造函数设置为私有属性,在类的内部完成实例化对象的创建
    				提供一个全局访问点来获取类内部创建好的对象)
    Simple Factory Pattern,简单工厂模式
             通过一个专门的类(工厂)来负责创建其他类的实例(具体产品),这些类都有一个共同的抽象类作为基类(抽象产品)。
    factory pattern,工厂模式同样属于类的创建型模式,也成为多态工厂模式	
             工厂模式多出了一个抽象工厂角色作为接口,实际的生产工作在具体工厂类中实现	
    Abstract Factory Pattern,抽象工厂模式
            一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构
    Bulider Pattern,建造者模式,也叫做生成器模式,是一种对象创建型模式
          	强调的是建造过程,要关注每一个部件的建造方式,以及各个部件的建造逻辑,最终组合出需要的对象
   
结构型模式   
   Proxy Pattern,代理模式 客户端只有通过Proxy来实现与被代理类的交互,并且在交互过程中 ,代理可以增加其它操作
   Decorator Pattern,装饰模式,也叫做包装模式,是结构型模式的一种:装饰模式的具体实现就是把一些功能封装在一个个单独的子类中
   Adapter Pattern 适配器模式 适配器模式可以将一个类的接口转换成客户希望的另一种形式的接口
   Composite Pattern,组合模式
    Bridge Pattern,桥接模式
	Facade Pattern,外观模式  Flyweight Pattern,享元模式 享元模式的目的就是使用共享技术来实现大量细粒度对象的复用。
行为型模式
    Template Pattern,模板方法模式 通过子类继承对抽象算法进行不同的实现来达到改变算法行为的目的
	Command Pattern,命令模式,是一种行为型设计模式
	Chain of Responsibility Pattern,CoR责任链模式,
	Strategy Pattern,策略模式
	Mediator Pattern,中介者模式
	Observer Pattern,观察者模式:
	   一种一对多的模式,多个观察者对象同时监听一个主题对象,一旦主题对象发生变化,能够自动通知所有的观察者对象。
	     它提供了一种关联对象之间的同步机制,他们之间通过通信来保持状态同步。
	Visitor Pattern,访问者模式
	    把数据结构和作用于数据结构上的操作进行了分离,在不修改已有类的前提下可以增加新的操作,而新增新的操作就相当于新增一个访问者。
	Memento Pattern,备忘录模式
	State Pattern,状态模式:通过改变对象的内部状态来达到改变对象行为的目的
	interpreter Pattern,解释器模式
	Iterator Pattern,迭代器模式

架构

--应对复杂系统的方式
 还是宏观层面的架构,无论是三种编程范式还是微服务架构,它们都在解决一个问题——分离控制和逻辑。
  所谓控制就是对程序流转的与业务逻辑无关的代码或系统的控制(如多线程、异步、服务发现、部署、弹性伸缩等)​,
  所谓逻辑则是实实在在的业务逻辑,是解决用户问题的逻辑。
  控制和逻辑构成了整体的软件复杂度,有效地分离控制和逻辑会让你的系统得到最大的简化

复杂系统的问题: 需求、环境和技术的不断变化,涉及的因素和角色众多,各种因素之间互相关联
     边界的选择取决于你想要了解的信息和出于何种目的进行考虑
     系统思维--应对问题的复杂性:将问题分解成更小的组成部分的过程,同时意识到每个部分对整个系统的影响
	 系统的工具:要素、连接和目标  全局、动态、关联  适应力、自组织、层次性
	           存量、流量和反馈回路
			   有限理性   时间延迟
    系统论--信息论--控制论
    耗散结构论、协同论、突变论称为“新三论”
	    耗散结构论: 
	    自组织: 是现代非线性科学和非平衡态热力学: 单元自律 短程通讯 微观决策
		突变论: 稳定状态进入不稳定状态 不稳定状态进入另一种稳定状态

内存与程序运行中的报错

 寄存器--堆heap 和栈stack
 stack 栈主要用于存储函数调用时需要的各种信息,以及函数执行过程中产生的临时数据。栈的特点是高效的内存分配和释放,但是大小有限,
    函数返回地址-函数的参数-局部变量
     1. 局部变量:在函数内部声明的局部变量会被存储在栈上		

纯虚函数

C++可以通过抽象类(Abstract Class)和纯虚函数(Pure Virtual Function)来模拟接口的概念‌
      没有直接提供接口关键字
     C++标准库本身并没有直接提供像Java或C#那样的“接口”关键字‌。然而,
    抽象类(Abstract Class)
	     C++语言中没有抽象类的概念 C++中通过纯虚函数实现抽象类。
	纯虚函数(Pure Virtual Function)
	   纯虚函数是没有函数体的虚函数,它强制派生类(子类)实现该函数
	   
	在C++中,这通过创建一个包含纯虚函数的抽象类来实现。  
       抽象类通常用作基类,派生类继承它并提供纯虚函数的实现。	

仓颉编程

虚拟机监视器(Hypervisor)	
	
Hypervisor的类型和特点
    Hypervisor有两种类型:类型1(裸机)和类型2(宿主机)。类型1 Hypervisor直接运行在硬件之	


定义操作符函数时需要在 func 关键字前面添加 operator 修饰符;
  操作符函数的 参数个数需要匹配对应操作符的要求;
  操作符函数只能定义在 class、interface、struct、enum 和 extend 中;
  操作符函数具有实例成员函数的语义,所以禁止使用 static 修饰符;
  操作符函数不能为泛型函数。
eg: public operator func -(): Point {  Point(-x, -y) }

在Java中,运算符是不能被重载的	
  没有运算符重载,但却将基础非常易用的运算符进行了重载
python重载:  __add__(self, other)  _sub__(self, other)  __mul__(self, other)  _truediv__(self, other)  __str__(self):
  绑定(binding)和重绑定(rebinding)

参考

c++类——类与类之间的关系 https://blog.csdn.net/xiaohei07/article/details/131676336	
架构整洁之道
https://github.com/puge-up/programming-cpp/tree/main
https://bbs.huaweicloud.com/blogs/397606
C++编译器合成默认构造函数的真相  https://bbs.huaweicloud.com/blogs/321795
C++编译器自动生成的函数  https://www.cnblogs.com/islch/p/16143768.html

标签:函数,--,模式,运算符,对象,C++,重载,设计模式,构造函数
From: https://www.cnblogs.com/ytwang/p/18595512

相关文章

  • [c++]c++ 工程代码中的debug时条件编译隐去的代码会影响程序运行的性能和耗时吗
    前言 理解在C++(或任何编程语言)中,使用条件编译(如通过#ifdef,#ifndef,#endif预处理指令)来根据调试(debug)或发布(release)模式包含或排除代码段,对程序在最终编译后的性能和耗时通常是没有直接影响的。这是因为条件编译指令是在编译之前处理的,它们决定了哪些代码会被编译器实际编......
  • Qt/C++离线读取全国任意经纬度高程海拔值/无任何依赖/纯原创代码解析
    一、前言说明做地图开发会遇到一个常规需求,就是获取当前经纬度对应的海拔高度,也叫做高程值,很遗憾各大地图厂商都未提供接口获取,可能是有明文规定,不能地图中提供对应的海拔高度值,于是需要另想他法,尽管谷歌地图在线的api接口是提供了海拔高度值,但是懂得都懂,国内哪里还能用谷歌地图?......
  • 2024年厦门市第31届小学生C++信息学竞赛试题与解析(第二部分填空题6-10)
    最长上升子序列参考程序:#include<iostream>#include<vector>#include<algorithm>//为了使用std::maxintlengthOfLIS(conststd::vector<int>&nums){if(nums.empty()){return0;}intn=nums.size();std::vector......
  • 2024年厦门市第31届小学生C++信息学竞赛试题与解析(第二部分填空题1-5)
    ......
  • 5.1.1 C++函数模板和类模板注意事项
    一)函数注意事项·1.自动类型推导,必须推导出一致的数据类型T,才可以用。·2.模板必须要确定出T的数据类型,才可以使用。(必须给出类型表达式)二)普通函数与函数模板的区别·1.普通函数调用时可以发生自动类型转换(隐式类型转换)。·2.1函数模板调用时,如果利用“自动类型推导......
  • ZZNUOJ_1077 : 字符串加密(C/C++/Java算法源码&注释)
    题目描述输入一串字符和一个正整数k,将其中的英文字母加密并输出加密后的字符串,非英文字母不变。加密思想:将每个字母c加一个序数k,即用它后面的第k个字母代替,变换公式:c=c+k。如果字母为z,则后一个字母是a,也就是字母字符形成一个圆。输入输入第一行是一个整数k,k是int范围......
  • ZZNUOJ_1274:位数和(C/C++/Java算法源码&注释)
    题目描述位数和即Digit-sum。一个整数的Digit-sum就是:十进制表示下的整数的各个位数的和,例如1234的Digit-sum是1+2+3+4=10,3443的Digit-sum是3+4+4+3=14. 现在问题是:给你三个正整数A,B和C,在A和B之间找一个整数X,使得X的Digit-sum与C的Digit-sum的最接近,如果存在多个X则......
  • 【C++】vector
    `vector`是一种容器,广泛存在于多种编程语言中,如C++、Rust、Java等。它是一种动态数组,可以存储任意类型的元素,并且可以根据需要自动调整大小。下面我将详细介绍`vector`的概念和使用方法,主要以C++中的`std::vector`为例。###1.概念-**动态数组**:与静态数组不同,`ve......
  • 设计模式——Adapter(适配器)模式
    摘要本文介绍了适配器模式(AdapterPattern),这是一种结构型设计模式,用于将一个类的接口转换成另一个接口以实现类之间的协同工作。文章详细阐述了适配器模式的定义、类型、作用、优点,并提供了使用场景和Spring框架下的示例代码。适配器模式通过解耦和扩展性,提高了系统的灵活性和......
  • 二叉树的C++实现
    文章目录一、二叉树存储的物理结构1.1二叉树基础知识1.2二叉树的存储1.2.1单个节点的存储:1.2.2二叉树的存储二、C++代码实现2.1每个二叉树节点结构体:2.2二叉树类的定义2.3方法实现一、二叉树存储的物理结构1.1二叉树基础知识(1)二叉树的定义:每个节点最多......