C++与C#的对比

本文对比了C#和C++在编译、运行、权限、变量表达与运算、条件分支、循环、类型转换、函数、面向对象等方面的差异。C#的编译过程包括生成CIL和JIT编译,运行依赖CLR,支持更安全的权限管理,以及如字符串字面量、checked函数等便捷特性。同时,C#的委托、泛型、lambda表达式等特性提供了更高效的编程体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

摘要

   考虑到mfc的学习已经稍微达到中级的入门,现阶段需要学习UE,而UE很多涉及C#知识。故开始C#的学习。之所以要换一门语言是考虑到MFC做前端属实事半功倍。学习另一门框架、语言,如果与自己已熟悉的知识体系映射起来,会极大提高学习效率。本文对二者的差异进行总结

正文

一、编译相关

MFC的编译

  就是C、C++语言的 预处理→编译→ 汇编→ 链接
  生成的.dll .exe 文件 直接运行就可以了,资源文件(图标 数据)大多在这些文件里直接嵌套进去了。

C# .NET的编译

  第一步 把C# 编译成 通用中间语言 (Common Intermediate Language,CIL) 生成的文件存在程序集中,这个程序集包含了熟悉的.exe文件、资源文件(图标、数据、序列化文件之类)也称元数据。

  第二步 把 通用中间语言代码编译成 本机代码(Just-In-Time编译器完成)

GAC (Global Assembly Cache)全局程序集 缓存

二、运行相关

c++程序的运行

  走的msvcr90.dll 之类的

c#程序的运行

  走的是CLR公共语言运行时。

三、权限相关

c++程序的权限

  直接访问系统API

c#程序的运行

  托管环境所支持的。
  内存管理就“基本”不需要程序员了。

四、变量表达与运算相关

C#胜于C++的特性

字符串字面值,“@”
对带有转义的字符串,之前:“C:\\Doc\\加油站.torrent”
使用“@”后:@“C:\Doc\加油站.torrent”

运算符优先级

C# 与 C++保持一致

优先级运算符
优先级由高到低++、 --(作前缀)、 +、 -、
* 、/、 %
+ 、-
=、*=、/=、%=、+=、-=
++、-- 作后缀

闲杂

 			string strName = "Baotong";
            strName = strName.PadLeft(10, '-');

这里参数写的是10 但是在左边添加了三个‘-’字符,是因为10是总长度

五、条件分支相关

Switch语句

  1. C++ case可以执行多个,而在C#中则属于异常!
  2. C# 骚操作:
			int key = 10;
            switch(key)
            {
                case int value when value < 10: //如果是正数则进入该分支
                   break;
                case int value when value > 10:
                    break;
                case var var1:// 变量类型 
                    Console.WriteLine(var1.GetType().Name);
                    break;
            }

六、循环相关

foreach语句

循环体里只能进行读,不能写

七、类型转换相关

C# 有个新特性 checked()函数,可以检测是否在类型转换时存在溢出!
string类型的ToDouble ToInt方法都会对溢出进行检查

八、函数相关

参数

  1. C# 支持函数参数 为 “参数数组”,这个特殊参数只能是最后一个参数,且需用关键字 params定义。
 		static int SumVars(params int[] vars)
        {
            int sum = 0;
            foreach(int var in vars)
            {
                sum += var;
            }
            return sum;
        }

        static void Main()
        {
            int nSum = SumVars(1, 2, 3, 4, 5, 6, 7);
        }
  1. C#的 ref、out 关键字等价于 C++ 的引用修饰 &,有一区别是:C#传递实参的时候也必须加上这个关键字,且ref传参前必须初始化,out使用时必须当做未初始化的值。
  2. C# 支持return多个参数,方法是使用元组
        static (int max , int min , double average) GetMaxMin(IEnumerable<int> num)
        {
            return (Enumerable.Max(num), Enumerable.Min(num), Enumerable.Average(num));
        }
        static void Main()
        {
            IEnumerable<int> numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            var result = GetMaxMin(numbers);
        }
        //Enumerable 用于查询的类 ,  IEnumerable 现在当做泛型参数理解
  1. 委托,对应c++的延迟绑定,就是让运行时决定 调用那个函数来执行。
class Program
    {
        delegate double ProcessDelegate(double param1, double param2);//1.定义
        static double Multiply(double param1, double param2) => param1 * param2;
        static double Divide(double param1, double param2) => param2 / param2;

        static void Main(string[] args)
        {
            ProcessDelegate process;
            Console.WriteLine("Enter 2 numbers separated with  a comma:");
            string input = Console.ReadLine();
            int commaPos = input.IndexOf(',');
            double param1 = Convert.ToDouble(input.Substring(0,commaPos));
            double param2 = Convert.ToDouble(input.Substring(commaPos+1,input.Length - commaPos -1));

            Console.WriteLine("Enter M to multiply or D to divide:");
            input = Console.ReadLine();
            if (input == "M")
                process = new ProcessDelegate(Multiply);//2.绑定
            else
                process = new ProcessDelegate(Divide);

            Console.WriteLine($"Result:{process(param1, param2)}");//3.调用
            Console.ReadKey();

            Console.ReadKey();        
        }
    }

九、面向对象相关

Object类

  可以把C#中Object 粗粗的理解为 C里面的指针,32位系统下指针的大小都是四个字节,不管是啥对象的指针。异曲同工,C#中Object是所有对象的基类,也就是可以用Object接收所有类。

继承类 接口实现的语法

   C#写法

public class MyClass : MyBase,IMyInterface
{
//首字母 I,一般表示该类为接口
}

接口的定义

public IMyInterface
{//接口成员
}

多态性的使用

//使用Object基类的GetType()方法,获取System.Type 类型的返回值
if(myObj.GetType() == typeof(类名(例如汽车类)))
{
	//加汽油![在这里插入图片描述](https://img-blog.csdnimg.cn/9e3541a980624879bf389b380ce46812.png)

}

VS编译器图标含义

在这里插入图片描述
在这里插入图片描述

C# 接口和抽象类的相同点与不同点

1、成员可以由派生类继承(相同)
2、不能直接实例化(相同)
3、派生类只能继承自一个基类,可以用继承链包含多个抽象类,而一个类可以使用多个接口。
4、抽象类可以拥有抽象成员和非抽象成员,而接口成员必须都在使用接口的类上实现。接口成员是公共的,但抽象类的成员各种各样。
5、接口不包含字段、构造函数、析构函数、静态成员或常量。

抽象类用作基类,不同继承类有共性的部分。
接口则主要用于类,各个实现有根本的区别。

C#中结构是值类型,对象是引用类型

  也就是说结构的复制是做的拷贝,而对象的复制传递的是指针。

C# 在vs编译器中快速创建属性

  输入prop 快速按两下TAB键。

C# 支持隐藏基类的成员

  C++如果子类重写了父类的方法,则通过基类指针调用该方法时也会执行子类的方法。这一点与C# “override”修饰的方法一致。C#若没这个关键字则基类指针还是执行的基类的方法。

C#强制调用基类的方法

  使用base关键字,base.DoMethod();

C# 支持一个类 分不同的文件定义

  !!!

C# 部分方法相关

  部分方法就是一个文件写申明,一个文件写实现,类似.h和.cpp那味。
C# 部分方法不能有返回值,任何参数不能是out修饰。编译时如果没有该方法没有实现则编译器直接把该方法抹去。

为啥部分方法不能有返回值?

  因为如果有返回值则可能有一个变量用来接收这个方法的返回值,编译器直接抹去这个值是不安全的。接收返回值的这个变量可能就成了随机数,有极大隐患。out修饰的参数也是类似的道理。

C# 封箱和拆箱

  封箱是把值类型转换为System.Object类型,或者转换为由值类型实现的接口类型。(子类 -> 父类)
  拆箱是相反的过程。

十 、比较相关

  C++ 与C# 都支持运算符(大于、小于、等于…)重载。此外C#有两个接口,分别是IComparable和IComparer。
IComparable:提供CompareTo()方法
IComparer:提供Compare()方法

//**下面这段代码是Class Person继承了IComparable接口,有啥用呢?
//*就是当我们把Class Person存储到list、queue等容器后,调用sort方法,则会按这个CompareTo规则进行排序
    class Person : IComparable
    {
        public string Name;
        public int Age;
        public Person(string name, int age)
        {
            Name = name;
            Age = age;
        }
        public int CompareTo(object obj)
        {
            if (obj is Person)
            {
                Person otherPerson = obj as Person;
                return this.Age - otherPerson.Age;
            }
            else
            {
                throw new ArgumentException(
                   "Object to compare to is not a Person object.");
            }
        }
    }
//**下面这段代码是Class Person继承了IComparer接口,与上面有啥区别?
//**Comparer 翻译过来是比较器的意思,也就是这个类就是做比较用的,比如可以在Compare方法中接收各种各样的类,判断类型进行比较输出即可。而上面继承IComparable则只能和自身的类比较。
 public class PersonComparerName : IComparer
    {
        public static IComparer Default = new PersonComparerName();
        public int Compare(object x, object y)
        {
            if (x is Person && y is Person)
            {
                return Comparer.Default.Compare(
                   ((Person)x).Name, ((Person)y).Name);
            }
            else
            {
                throw new ArgumentException(
                   "One or both objects to compare are not Person objects.");
            }
        }
    }

十一、泛型相关

  形式上换汤不换药,C# 的泛型也是尖括号指定类型。但实质上C# 的泛型的类型判断都是在运行时,而C++是编译期间确定的。有句总结很精辟:“泛型不止涉及集合,但集合特别适合泛型”。泛型的好处是简化代码,坏处就是代码可读性差。

十二 Lambda表达式

  Lambda表达式的学习,抓住其优势就行了。使用lambda表达式无非就是为了把一些很小的代码写成匿名函数,增强可读性。从写的角度来说,写不出来也无所谓,按照平常的子函数写法就行了。从读的角度来说,实在读不懂就先拆成子函数!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值