C++与C# 对函数隐藏的不同处理
2008-10-21 12:10
337 查看
看一段简单的C++代码
#include <iostream>
class A
{
public:
void f(float x)
{
std::cout << "A::f(float)" << std::endl;
}
void f(int x, int y)
{
std::cout << "A::f(int,int)" << std::endl;
}
};
class B : public A
{
public:
void f(int x)
{
std::cout << "B::f(int)" << std::endl;
}
};
int main(int argc, char * argv[])
{
B b;
b.f(2.3);
// b.f(2,3); occur error
return 1;
}
执行结果应该是什么呢?
记住这种情况不会实现函数重载的,因此调用b.f(2,3)会出现编译错误,而调用b.f(2.3)不会调用基类的f函数,而会调用派生类的f函数(参数类型隐性转换),函数隐藏的概念摘录如下
隐藏是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)
如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)
再看同样代码的C#实现
using System;
using System.Collections.Generic;
using System.Text;
namespace FunctionTest
{
class Program
{
static void Main(string[] args)
{
B b = new B();
b.f(2.3f);
b.f(2, 3); // work well
}
}
public class A
{
public void f(int x)
{
Console.WriteLine("A::f(int)");
}
public void f(int x, int y)
{
Console.WriteLine("A::f(int,int)");
}
}
public class B : A
{
public void f(float x)
{
Console.WriteLine("B::f(float)");
}
}
}
会发现与C++的不同之处,在C#中不会进行函数隐藏,即使派生类与基类同名,参数不同也能实现类似函数重载,执行结果是
A::f(float)
A::f(int,int)
这样的结果才会符合我们预期的设想,也许这也算是C++设计的一个不足之处吧
为了验证这真的算是函数重载么,把上面的程序简单改变一下,再看下面一段C#代码
using System;
using System.Collections.Generic;
using System.Text;
namespace FunctionTest
{
class Program
{
static void Main(string[] args)
{
B b = new B();
b.f(2);
b.f(2, 3); // work well
}
}
public class A
{
public void f(int x)
{
Console.WriteLine("A::f(int)");
}
public void f(int x, int y)
{
Console.WriteLine("A::f(int,int)");
}
}
public class B : A
{
public void f(float x)
{
Console.WriteLine("B::f(float)");
}
}
}
执行结果是
B::f(float)
A::f(int,int)
此时为什么没有调用基类的函数呢 这与普通的函数重载肯定也有不同之处,我的理解是派生类中的函数会有比基类更高的优先级,int能直接转换为float型,然后进行调用,反之float转换成int,是不能隐式进行的,所以调用了基类的函数。这只是我的理解,如果有更好的解释情留言告诉我。
#include <iostream>
class A
{
public:
void f(float x)
{
std::cout << "A::f(float)" << std::endl;
}
void f(int x, int y)
{
std::cout << "A::f(int,int)" << std::endl;
}
};
class B : public A
{
public:
void f(int x)
{
std::cout << "B::f(int)" << std::endl;
}
};
int main(int argc, char * argv[])
{
B b;
b.f(2.3);
// b.f(2,3); occur error
return 1;
}
执行结果应该是什么呢?
记住这种情况不会实现函数重载的,因此调用b.f(2,3)会出现编译错误,而调用b.f(2.3)不会调用基类的f函数,而会调用派生类的f函数(参数类型隐性转换),函数隐藏的概念摘录如下
隐藏是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)
如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)
再看同样代码的C#实现
using System;
using System.Collections.Generic;
using System.Text;
namespace FunctionTest
{
class Program
{
static void Main(string[] args)
{
B b = new B();
b.f(2.3f);
b.f(2, 3); // work well
}
}
public class A
{
public void f(int x)
{
Console.WriteLine("A::f(int)");
}
public void f(int x, int y)
{
Console.WriteLine("A::f(int,int)");
}
}
public class B : A
{
public void f(float x)
{
Console.WriteLine("B::f(float)");
}
}
}
会发现与C++的不同之处,在C#中不会进行函数隐藏,即使派生类与基类同名,参数不同也能实现类似函数重载,执行结果是
A::f(float)
A::f(int,int)
这样的结果才会符合我们预期的设想,也许这也算是C++设计的一个不足之处吧
为了验证这真的算是函数重载么,把上面的程序简单改变一下,再看下面一段C#代码
using System;
using System.Collections.Generic;
using System.Text;
namespace FunctionTest
{
class Program
{
static void Main(string[] args)
{
B b = new B();
b.f(2);
b.f(2, 3); // work well
}
}
public class A
{
public void f(int x)
{
Console.WriteLine("A::f(int)");
}
public void f(int x, int y)
{
Console.WriteLine("A::f(int,int)");
}
}
public class B : A
{
public void f(float x)
{
Console.WriteLine("B::f(float)");
}
}
}
执行结果是
B::f(float)
A::f(int,int)
此时为什么没有调用基类的函数呢 这与普通的函数重载肯定也有不同之处,我的理解是派生类中的函数会有比基类更高的优先级,int能直接转换为float型,然后进行调用,反之float转换成int,是不能隐式进行的,所以调用了基类的函数。这只是我的理解,如果有更好的解释情留言告诉我。
相关文章推荐
- C++ 和C#中 数字前有0的不同处理
- C++ 和C#中 数字前有0的不同处理
- 再谈static在C++和C#中的不同处理
- C与C++对于全局变量的不同处理之处
- c# 基础 一些与c++不同的
- C#将Bitmap转换成byte[],可以传给C++处理,与Opencv通信。
- 记录一下C++和C#中的字符串处理与编码格式的问题
- C#和java,C#和C++各有什么不同
- android NDK中对C和C++的处理不同,导致使用方法不同
- c#调用C++时处理tchar *转字符串
- C++、Java和C#语言在处理“虚拟私有方法”上的差异
- 编写高效的C#图像处理程序(4) Rgb=>Lab,C# vs. C++(VC)
- 最接近C# 的Event的C++处理
- C#与C++字符编码的不同
- JAVA异常处理 与C++的不同
- C与C++对__declspec(dllimport)和__declspec(dllexport)标志符号不同处理
- C++与C#之不同
- 使用C#处理WebBrowser控件在不同域名中的跨域问题
- 字符串处理问题(c++和c#两种解法)
- C、C++、C#简单代码编译结果的不同!