使用 C# 学习面向对象编程:第 4 部分

C# 构造函数

第 1 部分仅介绍了类构造函数的基础知识。 在本课中,我们将详细讨论各种类型的构造函数。

属性类型

  • 默认构造函数
  • 构造函数重载
  • 私有构造函数
  • 构造函数链
  • 静态构造函数
  • 析构函数

请注意构造函数的一些基本概念,并确保你的理解非常清楚,否则你无法理解 OOP(构造函数)。

  1. 构造函数的名称与类名相同。
  2. 构造函数的目的是为了初始化成员变量。
  3. 创建对象时会自动调用构造函数。
  4. 构造函数没有任何返回类型,甚至没有 void。
  5. 如果我们希望自动执行某些代码,那么我们想要执行的代码必须放在构造函数中。
  6. 我们不能明确调用构造函数。

C# 构造函数的一般形式如下。

modifier constructor_name(parameters)
{// constructor body
}

修饰符可以是 private、public、protected 或 internal。构造函数的名称必须是其定义所属类的名称。构造函数可以接受零个或多个参数。零个参数(即无参数)的构造函数称为默认构造函数。请记住,构造函数没有返回类型。

默认构造函数

无参数的构造函数称为默认构造函数。请记住,构造函数没有返回类型。默认构造函数只是调用直接基类的无参数构造函数。

例子

using System;namespace DefaultConstructors
{class Program{static void Main(string[] args){// 创建 car 类的一个实例 sportscar,调用默认构造函数car sportscar = new car();// 打印 sportscar 的 model_Id 属性值Console.WriteLine("Car Model is :{0} ", sportscar.model_Id);// 打印 sportscar 的 Maker_Name 属性值Console.WriteLine("Car Name is :{0}", sportscar.Maker_Name);// 等待用户按下任意键继续执行程序Console.ReadKey();}// 定义 car 类class car{// 私有字段 model,表示车型private int model = -1;// 私有字段 maker,表示制造商private string maker = string.Empty;// 默认构造函数public car(){// 默认构造函数的主体是空的,可以添加初始化逻辑}// 公共只读属性 model_Id,用于获取 model 字段的值public int model_Id{get {return model;}}// 公共只读属性 Maker_Name,用于获取 maker 字段的值public string Maker_Name{get{return maker;}}}}
}

输出


在这个简单的例子中,我们有一个无参数或零参数的构造函数,它是类的默认构造函数。上述示例的输出是空成员变量。

请注意另外一点;如果我们从示例 1 中删除以下代码,则输出是相同的。

public car()
{//Default Constructor
}

这意味着如果我们没有定义类的构造函数,系统将调用默认构造函数。

构造函数重载

首先,我们来讨论一下构造函数重载的目的;对前面的主题有清晰的理解非常重要。在设计 OOP 模型时存在许多复杂的情况,我们需要为类的不同目的初始化一组不同的成员变量。所以我们需要使用构造函数重载。构造函数重载的定义是。

和成员函数一样,构造函数也可以在类中重载。重载的构造函数必须在参数数量和/或参数类型和/或参数顺序上有所不同。

例子

using System;namespace ConstructorsOverloading
{class Program{static void Main(string[] args){// 使用无参数构造函数创建 car 类的一个实例car sportscar1 = new car();// 使用包含两个参数(model 和 maker)的构造函数创建 car 类的一个实例car sportscar2 = new car(2013, "mercedes");// 使用包含两个参数(maker 和 Enginetype)的构造函数创建 car 类的一个实例car sportscar3 = new car("mercedes", 7.8);// 输出使用无参数构造函数创建的 sportscar1 的属性值Console.WriteLine("Constructor without arguments");Console.WriteLine("Car Model is :{0} ", sportscar1.model_Id);Console.WriteLine("Car Name is :{0}", sportscar1.Maker_Name);Console.WriteLine("Car Engine Power is :{0}", sportscar1.Engine);// 输出使用包含两个参数的构造函数创建的 sportscar2 的属性值Console.WriteLine("\nConstructor with two arguments");Console.WriteLine("Car Model is :{0} ", sportscar2.model_Id);Console.WriteLine("Car Name is :{0}", sportscar2.Maker_Name);Console.WriteLine("Car Engine Power is :{0}", sportscar2.Engine);// 输出使用包含两个参数的构造函数创建的 sportscar3 的属性值Console.WriteLine("\nConstructor with two arguments");Console.WriteLine("Car Model is :{0} ", sportscar3.model_Id);Console.WriteLine("Car Name is :{0} ", sportscar3.Maker_Name);Console.WriteLine("Car Engine Power is :{0}", sportscar3.Engine);// 等待用户按下任意键继续执行程序Console.ReadKey();}// 定义 car 类class car{// 私有字段,表示车型private int model = -1;// 私有字段,表示制造商private string maker = string.Empty;// 私有字段,表示发动机类型private double Enginetype = 0.0;// 无参数的默认构造函数public car(){// 默认构造函数的主体是空的,可以添加初始化逻辑}// 包含两个参数(model 和 maker)的构造函数public car(int _model, string _maker){model = _model;maker = _maker;}// 包含两个参数(maker 和 Enginetype)的构造函数public car(string _maker, double _power){maker = _maker;Enginetype = _power;}// 公共属性,用于获取和设置 model 字段的值public int model_Id{get{return model;}set{model = value;}}// 公共属性,用于获取和设置 maker 字段的值public string Maker_Name{get{return maker;}set{maker = value;}}// 公共属性,用于获取和设置 Enginetype 字段的值public double Engine{get{return Enginetype;}set{Enginetype = value;}}}}
}

输出


亲爱的读者,请注意,在这个例子中,我们使用三个不同的对象重载了构造函数,它们是sportscar1、sportscar2 和 sportscar3。

我们注意到

  • sportscar1 没有参数(默认构造函数超出了主题范围)。因此该成员变量具有在初始化时分配的默认值。
  • sportscar2 有两个参数,分别用值 2013 和 Mercedes 初始化成员变量 model 和 name,但没有初始化 Enginetype 变量,因此它具有默认值零。
  • sportscar3 有两个参数,分别用值 Mercedes 和 7.8 初始化成员变量 name 和 Enginetype,但不初始化 model 变量,因此它具有默认值 -1。

私有构造函数

亲爱的读者,我们知道,私有访问修饰符有点特殊。我们既不能创建类的对象,也不能仅使用私有构造函数来继承类。但是,是的,我们可以在类中拥有一组公共构造函数以及私有构造函数,并且公共构造函数可以通过构造函数链从类内部访问私有构造函数。私有构造函数通常用于仅包含静态成员的类中。

using System;namespace PrivateConstructors
{class Program{static void Main(string[] args){// 使用包含 model 参数的构造函数创建 car 类的一个实例car sportscar = new car(2013);Console.Read();}class car{// 公共字段,表示汽车名称public string carname;// 私有的默认构造函数private car(){// 初始化 carname 字段carname = "lamborghini";}// 公共的构造函数,包含一个 int 型的 model 参数// 该构造函数通过 :this() 调用私有的默认构造函数public car(int model) : this(){// 打印车型年份Console.WriteLine("Model Year:{0}", model);// 打印制造商名称Console.WriteLine("Maker Name:{0}", carname);}}}
}

这是一个非常简单的私有构造函数的例子,其中我们使用公共构造函数来调用私有构造函数。

构造函数链

亲爱的读者,当一个构造函数调用同一个类或该类的基类中的另一个构造函数时,这被称为构造函数链。这是避免代码重复的非常有用的技术。

using System;namespace Constructorchaining
{class Program{static void Main(string[] args){// 使用包含 engine 参数的构造函数创建 car 类的一个实例car sportscar = new car(7.8);Console.Read();}class car{// 公共字段,表示汽车名称public string carname;// 公共字段,表示车型年份public int model;// 公共字段,表示发动机类型public double engine;// 包含一个 carname 参数的构造函数public car(string _carname){carname = _carname;}// 包含一个 model 参数的构造函数,并调用包含 carname 参数的构造函数public car(int _model) : this("lamborghini"){model = _model;}// 包含一个 engine 参数的构造函数,并调用包含 model 参数的构造函数public car(double _engine) : this(2013){engine = _engine;// 打印车型年份Console.WriteLine("Model Year:{0}", model);// 打印制造商名称Console.WriteLine("Maker Name:{0}", carname);// 打印发动机类型Console.WriteLine("Engine Type:{0}", engine);}}}
}

在前面的例子中,我们创建了三个不同的类,它们都具有相同的名称 car 和不同的参数类型,每个类都链接前一个类来调用另一个构造函数。

静态构造函数

静态构造函数是一种特殊类型,不采用访问修饰符,也不具有参数。在创建第一个实例或引用任何静态成员之前,会自动调用它以初始化类。静态构造函数不会被直接调用。用户无法控制静态构造函数的执行。

using System;namespace staticconstructors
{class Program{// 定义 car 类public class car{// 静态构造函数static car(){// 打印静态信息,静态构造函数在类第一次被使用前自动调用,并且只调用一次System.Console.WriteLine(@"Lamborghini is the best sports car owned by Audi AG 1998 (its static info)");}// 静态方法 Drivepublic static void Drive(){// 打印稳定公司信息System.Console.WriteLine("Audi is the stable company");}}// 主程序入口点static void Main(){// 调用 car 类的静态方法 Drivecar.Drive();// 再次调用 car 类的静态方法 Drivecar.Drive();// 等待用户按下任意键继续执行程序Console.ReadKey();}}
}

输出


注意,静态构造函数在第一次加载类时被调用。当我们再次调用“car.Drive”时,它不会调用静态构造函数。

析构函数

亲爱的读者,当我们使用 OOP 并在系统内存中创建对象时,需要从系统内存中清除不需要的对象。.NET 框架内置了垃圾收集功能,用于释放未使用对象占用的内存。析构函数是一个与类名同名但以字符 ~ 开头的函数。析构函数不能有任何修饰符 private、public 等。

例子

class car
{// 公共构造函数public car(){// 构造函数,在创建对象实例时调用// 可以在这里进行对象的初始化操作// 比如分配资源,设置初始状态等}// 析构函数~car(){// 析构函数,在对象被垃圾回收时调用// 可以在这里进行对象的清理操作// 比如释放资源,关闭文件,断开网络连接等}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/25893.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从入门到精通:进程间通信

引言 在现代操作系统中,进程是程序运行的基本单位。为了实现复杂的功能,多个进程常常需要进行通信。进程间通信(Inter-Process Communication, IPC)是指多个进程之间进行数据交换的一种机制。IPC的主要目的包括数据传输、资源共享…

WDF驱动开发-电源策略(三)

多组件设备的 KMDF 驱动程序只能将请求发送到处于活动状态的组件。 通常,驱动程序将 I/O 队列分配给组件或组件集。 首先考虑分配给单个组件的队列。 驱动程序在组件变为活动状态时启动队列,并在组件空闲时停止队列。 因此,当 KMDF 调用队列…

生成式人工智能重置:从初期热潮到战略扩展

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

PyTorch学习8:多分类问题

文章目录 前言一、说明二、示例1.步骤2.示例代码 总结 前言 介绍如何利用PyTorch中Softmax 分类器实现多分类问题。 一、说明 1.多分类问题的输出是一个分布,满足和为1. 2.Softmax 分类器 3.损失函数:交叉熵损失 torch.nn.CrossEntropyLoss() 二、…

运维开发详解:DevOps 理念下的高效运维实践

目录 前言 1、 运维开发的核心概念 2、 运维开发的技术栈 3、运维开发的实践案例 4、 运维开发的挑战与机遇 5、 运维开发的未来发展趋势 6、运维开发概念 7、运维开发的角色 8、成为一名优秀的运维开发工程师 9、总结 前言 随着互联网业务的快速发展,传…

虚拟化 之一 详解 jailhouse 架构及原理、软硬件要求、源码文件、基本组件

Jailhouse 是一个基于 Linux 实现的针对创建工业级应用程序的小型 Hypervisor,是由西门子公司的 Jan Kiszka 于 2013 年开发的,并得到了官方 Linux 内核的支持,在开源社区中获得了知名度和吸引力。 Jailhouse Jailhouse 是一种轻量级的虚拟化…

微软如何打造数字零售力航母系列科普13 - Prime Focus Technologies在NAB 2024上推出CLEAR®对话人工智能联合试点

Prime Focus Technologies在NAB 2024上推出CLEAR对话人工智能联合试点 彻底改变您与内容的互动方式,从内容的创建到分发 洛杉矶,2024年4月9日/PRNewswire/-媒体和娱乐(M&E)行业人工智能技术解决方案的先驱Prime Focus Techn…

架构师如何评估团队成员的成熟度

评估团队成员的成熟度是一个涉及观察、沟通和反馈的过程。以下是一些方法和步骤,可以帮助你评估团队成员的成熟度,无论是在技术能力、还是职业发展方面: 设定评估标准:首先,明确你希望评估的成熟度方面,比…

人工智能在医学领域的应用及技术实现

欢迎来到 Papicatch的博客 目录 🍉引言 🍉 医学影像分析 🍈技术实现 🍍数据准备 🍍模型构建 🍍模型训练 🍍模型评估 🍍应用部署 🍈示例代码 🍉 基因…

操作系统真象还原:内存管理系统

第8章-内存管理系统 这是一个网站有所有小节的代码实现,同时也包含了Bochs等文件 8.1 Makefile简介 8.1.1 Makefile是什么 8.1.2 makefile基本语法 make 给咱们提供了方法,可以在命令之前加个字符’@’,这样就不会输出命令本身…

微信小程序使用 “云函数“ 获取 “openid“

文章目录 1.前期准备2.具体操作步骤 1.前期准备 必须使用云开发已经配置好云开发 2.具体操作步骤 1.进入小程序开发工具→在云函数目录上右键→选中新建云函数 创建结束,自动上传(必须确认已经上传才生效) 2.进入对应页面的js文件&#…

QT 信号和槽 信号关联到信号示例 信号除了可以绑定槽以外,信号还可以绑定信号

信号除了可以关联到槽函数,还可以关联到类型匹配的信号,实现信号的接力触发。上个示例中因为 clicked 信号没有参数,而 SendMsg 信号有参数,所以不方便直接关联。本小节示范一个信号到信号的关联,将按钮的 clicked 信号…

【优化过往代码】关于vue自定义事件的运用

【优化过往代码】关于vue自定义事件的运用 需求说明过往代码优化思路优化后代码(Vue2)遇到问题记录 Vue2官方自定义指令说明文档 Vue3官方自定义指令说明文档 需求说明 进入某些页面需要加载一些外部资源,并在资源加载完后进行一些处理&…

51单片机数码管显示的计数器,按键按下暂定,再次按下继续。(按键功能使用中断实现)

1、功能描述 数码管显示的计数器,按键按下暂定,再次按下继续。(按键功能使用中断实现) 2、实验原理 按键与中断:使用单片机的外部中断功能来检测按键动作,实现非阻塞的按键检测。 中断服务程序&…

十四、OpenAI之助手API(Asistants API)

助手API允许你在自己的应用系统中构建一个AI助手。助手有指令,能利用模型、工具和文件响应用户的查询。助手API目前支持3种类型的工具:代码交互,文件搜索和函数调用。 你可以使用助手后台探索助手的能力,或通过这个指南的大纲一步…

【栈】2751. 机器人碰撞

本文涉及知识点 栈 LeetCode2751. 机器人碰撞 现有 n 个机器人,编号从 1 开始,每个机器人包含在路线上的位置、健康度和移动方向。 给你下标从 0 开始的两个整数数组 positions、healths 和一个字符串 directions(directions[i] 为 ‘L’ …

MySQL-数据处理函数

026-distinct去重 select job from emp;加个 distinct 就行了 select distinct job from emp;注意:这个去重只是将显示的结果去重,原表数据不会被更改。 select 永远不会改变原数据 select distinct deptno, job from emp order by deptno asc;027-数…

步态控制之足旋转点(Foot Rotation Indicator, FRI)

足旋转点(Foot Rotation Indicator, FRI) 足旋转点是人形机器人步态规划中的一个关键概念,用于描述步态过程中机器人脚部的旋转和稳定性。FRI 可以帮助确定机器人在行走时是否稳定,以及如何调整步态以保持稳定。下面详细介绍FRI的原理,并举例说明其应用。 足旋转点(FRI…

R语言统计分析——图形的简单示例

参考资料:R语言实战【第2版】 1、示例一 # 绑定数据框mtcars attach(mtcars)# 打开一个图形窗口并生成一个散点图plot(wt,mpg)# 添加一条最优拟合曲线abline(lm(mpg~wt))# 添加标题title("Regression of MPG on weight") # 解除数据框绑定 detach(mtcar…

ES8.13 _bulk报错Malformed content, found extra data after parsing: START_OBJECT解决

在使用elaticsearch8.13.0使用批量创建索引时,根据谷粒中说的es7.9方法去批量操作请求: http://127.0.0.1:9200/shop/_doc/_bulk 注意1:设置header为Content-Type:application/x-ndjson,否则请求报错: {"error": &qu…