`
dongwenhua
  • 浏览: 3217 次
  • 性别: Icon_minigender_2
  • 来自: 北京
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

从C/C++到C#之二 函数

    博客分类:
  • C#
阅读更多
函数参数引用传递与值传递:
C#对函数参数做了更明确的标示,使得程序更加清晰可读,通过使用in和out关键字说明了参数的作用,in修饰的参数在形参和实参结合的时候会生成副本,这样对形参的修改就不会对实参产生影响(副作用),因为这个函数内部使用不是实参而是生成的那个副本。out关键字函数对形参的修改会对实参产生副作用的,这样out的意思就是说我要用这个参数作为返回值。这点和C++引用传递的语义是类似的,函数对参数的修改会反映在实参上,这样我就可以得到最终变化的结果,其语义就是return的作用一样。没有in,out修饰默认是in.
public void InternalMagic(int x)
{
   x+=100;
}

int i=100;
InternalMagic(i);
Console.WriteLine(i);

输出是// Output will be '100' -- easy, little magic !-_-
public void InternalMagic(out int x)
{
   x+=100;
}

int i=100;
InternalMagic(i);
Console.WriteLine(i);
输出是// Output will be '200' -- easy, little magic !-_-

这两个例子我们看到了in和out的区别


传递值和引用的区别:
上次提到过引用类型和值类型,引用类型其实就是C++的指针类型的类似,是通过一个间接的东西持有一个值(对象),如StringBuffer buffer = new StringBuffer();这个buffer是引用类型,他得特点是复制不会拷贝原来的对象:
StringBuilder first = new StringBuilder(“Hello,”);
StringBuilder second = first;

这段代码其实first和second都指向同一段内存空间,里面的内容是”Hello,”.
StringBuilder first = new StringBuilder(“Hello,”);
StringBuilder second = first;
first.Append ("world");
first = null;
Console.WriteLine (second);


结果是Hello,world.我们对first的修改会影响到second.
知道这些后我们看看传递值和引用的问题吧,这个问题相当让人迷惑:
void Foo (StringBuilder x)
{
    x = null;
}
StringBuilder y = new StringBuilder();
y.Append ("hello");
Foo (y);
Console.WriteLine (y==null);

打印出false,我们前面说了in类型的参数传递函数对形参x的修改不会影响实参y的,所以
y!=null.
我们再看一个例子:
void Foo (StringBuilder x)
{
    x.Append (" world");
}

StringBuilder y = new StringBuilder();
y.Append ("hello");
Foo (y);
Console.WriteLine (y);

结果会使hello world.是不是很让人迷惑啊?修改x怎么y也变了呢,和上面的不是矛盾了么?我们前面已经说了引用类型和值类型的区别了,这个问题就会容易理解一些了:
实参y作为参数传递的时候的确产生了副本,但实参y是个引用类型,生成了一个引用的副本,不妨叫做y1,StringBuffer对象”hello”不会产生副本,这样y1让去操作StringBuffer对象”hello”,append(“ world”)当然会影响实参y了所指的同一个StringBuffer对象”hello”了,因为他们指向同一个StringBuffer对象”hello”。而上面的例子,x=null.这个只是修改了副本的指向一个null的东东,对实参y没有影响,还是指向原来的。
使用ref修饰:
void Foo (ref StringBuilder x)
{
    x = null;
}

...

StringBuilder y = new StringBuilder();
y.Append ("hello");
Foo (ref y);
Console.WriteLine (y==null);

这次打印出True了?ref修饰起什么作用的,这个东西和C++的&作用一样,引用传递,
参数传递的时候不会产生副本,对形参的修改会反映在实参上。所以x=null;导致了y也为
null了。
ref修饰和out修饰的区别:
ref和out修饰的效果是一样的,都是参数传递的时候不产生副本,但是他们的目的是不一样的,out的目的是这个参数作为返回值用,而ref的目的是形参不生成副本。
void Foo (out int x)
{
    // 不能去读x,int a = x 是不允许的,x默认的语义是没有赋值过

//必须赋值之后才能正常结束。    
x = 10;

    // 赋值之后才能去读。
    int a = x;
}

// y没有被初始化
int y;

// y作为out参数传递,没有被初始化
Foo (out y);

// 现在y已经有值了,他和返回值的语义相同,所以我们叫做out参数
Console.WriteLine (y);

输出为10
从上面的例子我们可以看到三点不同:
1、out修饰的实参传递之前是不需要被复制的
2、out参数被认为是没有被初始化的,所以你不能在他被复制之前去读它
3、out参数函数结束之前需要被赋值。

C#需要传递数组的时候需要使用params,这点和C++没有params修饰的效果是一样的:
  public class Test
  {
    public static void Main () {
        Console.WriteLine (add (1, 2, 3, 4).ToString());
    }

    public static int add (params int[] array) {
       int sum = 0;
       foreach (int i in array)
           sum += i;
       return sum;
    }
}



函数重载:
函数重载就是一个函数的名字相同,它的参数和修饰不同:
和C/C++一样返回值是不能作为重载的依据的。
我们看看C#的一些特殊的修饰:
Fun(int)和Fun(ref int) or Fun(out int)
是可以共存的,也就是说他们是重载的
但Fun(ref int) 和 Fun(out int)是不能共存的,他们不是重载的
判断重载的依据是:
函数名相同,调用这个函数的时候不会有歧义(不知道是调用具有这个函数名中的哪个?)
也就是函数名相同并且可以在一个作用于内共存的函数。
分享到:
评论

相关推荐

    C/C++和C#混合编程

    因此,如何实现C/C++与C#之间的混合编程,成为了开发者关注的焦点之一。 #### 技术背景 C#和C++在编译过程中的区别主要体现在它们的目标代码上:C#编译成微软中间语言(MSIL),而C++通常直接编译成本地机器码。...

    C/C++/C#笔试题目

    在IT行业中,编程语言是构建软件的基础,C、C++和C#这三种语言各具特色,被广泛应用于不同的领域。对于求职者来说,掌握这些语言的笔试题目可以帮助提升技术能力,了解企业对程序员的基本要求。下面将详细介绍C、C++...

    C++结构体/函数定义转换C#函数定义/结构体

    总之,从C++到C#的转换涉及类型映射、结构体布局、函数签名定义等多个方面。通过理解两种语言之间的差异,以及利用适当的工具,我们可以有效地完成这种转换。在实际操作中,还需要注意平台兼容性、异常处理、内存...

    C/C++/C#开发手册资料

    在IT行业中,C、C++和C#是三种至关重要的编程语言,它们各自拥有独特的特性和用途。这份“C/C++/C#开发手册资料”很可能是为了帮助开发者深入理解和熟练掌握这三种语言而编写的综合资源。下面,我们将详细探讨这些...

    c/c++/c#/vb/vb.net全局钩子

    在C/C++、C#、VB/VB.NET等编程语言中,实现全局钩子可以让你的应用程序捕获到整个系统范围内的特定事件,而不仅仅是你自己的应用程序。这种技术在开发调试工具、安全软件、输入法编辑器或监控用户行为的应用程序时...

    Demo: c/c++动态库(DLL)调用,c#等其他语言调用c/c++的DLL

    3. **C++动态库调用C动态库**:由于C语言的ABI(应用程序二进制接口)兼容性,C++代码可以直接调用C语言编写的DLL。只需确保C++函数声明遵循C语言的命名约定(通常是extern "C"),并且C语言的DLL导出函数不使用C++...

    C#调用C/C++ Dll中函数实例代码

    本文将详细介绍如何在C#中使用P/Invoke调用C/C++ DLL中的函数,并处理输入、输出字符串参数和结构类型参数。 首先,我们需要理解P/Invoke的概念。P/Invoke是.NET框架提供的一种机制,用于使托管代码能够访问非托管...

    使用Swig转换C++库到C#示例代码

    总的来说,这个示例提供了从C++到C#的完整转换过程,对于跨语言开发和理解Swig工具的使用非常有帮助。它不仅展示了如何利用Swig进行接口生成,还提供了实际的测试案例,以便开发者验证和理解转换后的代码功能。通过...

    统计某一个文件的代码函数,可以统计不同的编程语言,例如:C/C++、c#、JAVA、html、JavaScript

    统计某一个文件的代码函数,可以统计不同的编程语言,例如:C/C++、c#、JAVA、html、JavaScript

    C,C++转C#字典

    从C/C++到C#的代码迁移是一项细致且复杂的任务,需要对两种语言的特点都有深入了解。本文通过具体的示例介绍了数据类型转换、变量传递、函数调用等方面的关键点,希望对正在进行此类工作的开发者有所帮助。在实际...

    C#调用c++函数的dll文件,同时实现c++调用c#函数

    总的来说,C#调用C++ DLL和C++调用C#函数是通过.NET Framework的互操作特性实现的,包括P/Invoke和C++/CLI。这种方式在处理系统级操作、利用现有C++库或需要高性能计算时非常有用。解压后的两个项目"Dll3"和...

    C# 捕获C/C++异常的例子

    在本文中,我们将深入探讨如何在C#环境中捕获源自C/C++代码的异常,这对于跨语言开发或者使用C++库的C#项目至关重要。 C# 提供了一套强大的异常处理机制,它基于`try-catch`块来捕获和处理运行时错误。然而,C++的...

    C#在C++中注册回调函数

    在跨语言编程中,有时我们需要在C#代码中定义的函数能够在C++环境中被调用,这种情况通常通过回调函数来实现。本示例"CallbackTestCpp"将详细讲解如何在C#中定义一个函数,然后在C++项目中注册并执行这个函数。这...

    [价值百元][连载]c/c++/c#程序员实用大全(第四章 函数)

    本书对Oracle的WebDB 的基本概念、结构、组件,利用WebDB 创建应用程序系统和Web 站点,以及管理和维护WebDB 安全性等内容进行了详细介绍。如果喜欢请购买正版图书,请不要把此书用作任何商业用途。

    CLI/C++反射机制交互C#、C++

    描述中提到的“C# 通过托管C++调用本地C++ Dll文件”,这一过程涉及到以下步骤: 1. **创建C++/CLI接口**:在CLI/C++工程中定义一个接口,该接口将作为C#和C++之间的桥梁。接口应包含C++ DLL中实现的方法签名。 2....

    C/C++程序四书五经

    C语言不仅为后续的面向对象语言如C++、Java和C#等奠定了基础,而且在系统编程、嵌入式编程等领域持续发挥着核心作用。C语言的诞生标志着现代程序语言革命的开端,其简洁高效、强大的表达力、跨平台的移植性,使其...

    C# 调用C++DLL(函数参数包含指针)

    总结来说,C#调用C++DLL并处理指针参数涉及到P/Invoke、函数原型声明、指针类型映射、内存管理和异常处理等多个环节。理解这些细节是成功进行跨语言互操作的关键。在实际开发中,务必确保所有操作都遵循安全规范,以...

    C#调用C++动态库,执行回调函数并传递结构体参数

    在IT领域,跨语言通信是常见的需求之一,尤其是在C#和C++的混合编程中。本文将详细探讨如何在C#中调用C++编写的动态链接库(DLL),执行回调函数并传递结构体参数。这涉及到.NET Framework的P/Invoke(Platform ...

    VB C/C++ C#中自定义数据结构源码

    VB(Visual Basic)、C/C++以及C#都是广泛使用的编程语言,它们各自提供了不同的方式来创建和使用自定义数据结构。本篇文章将深入探讨这三种语言中自定义数据结构的实现方式、比较它们之间的差异,并介绍在实际应用...

    C#实现C++dll回调函数.rar

    C++ DLL中的回调函数通常声明为`extern "C"`,以避免C++的名称修饰(name mangling),使得C#能够正确识别。同时,我们需要定义一个函数,该函数接受C#的委托类型,并将其转换为C++的函数指针。 2. **C#的委托定义...

Global site tag (gtag.js) - Google Analytics