C++ 的面向对象三个特性 --继承、封装、多态的实现 ===》编译时多态

C++支持两种多态性:编译时多态性,运行时多态性。

  • 编译时多态性:通过重载函数实现。
  • 运行时多态性:通过虚函数实现。

编译时多态 的 “重载” :

1、重载是什么:

函数重载是指在同一作用域内,可以有一组具有相同函数名,不同参数列表(参数个数、类型、顺序)的函数,这组函数被称为重载函数。(一般的使用场景是类中 的不同同名不同参数列表的函数 来实现 这个“编译时多态”)

2、重载函数的作用 && 为什么要出现重载函数?

重载函数通常用来声明一组功能相似的函数,这样做减少了函数名的数量,避免了名字空间的污染,对于程序的可读性有很大的好处。

3、C++ 如何实现重载 ?

C++函数 重载 的底层原理 是基于 编译器name mangling 机制(重命名机制)。每个成员函数,经过name mangling 转换后,都会生成唯一的标识符,并且这个标识符只与函数名与函数参数类型有关,以此来支持函数重载。

由于:name mangling 后得到的函数标识符与返回值类型是无关的,因此函数重载与返回值类型无关。

int Add(int left, int right)
{
	return left + right;
}

double Add(double left, double right)
{
	return left + right;
}
 
long Add(long left, long right)
{
	return left + right;
}

上述三个代码会被重命名为:

"int __cdecl Add(int,int)" (?Add@@YAHHH@Z)
"double __cdecl Add(double,double)" (?Add@@YANNN@Z)
"long __cdecl Add(long,long)" (?Add@@YAJJJ@Z)

因此,编译器 可以顺利的找到 到底是调用的哪个函数

4.  一个问题:除了参数列表不同以外,还有其他的区分同名重载函数的方式吗? --  const 修饰的成员函数

class Number { 
private:
  int val_;

public:
  int val()            {return val_;}
  int val() const      {return val_;}

};

上述代码没有出现问题,理论上说,函数列表一致的同名函数会出现冲突,为什么上述代码没没有出错呢?

原因是:对于类中的成员函数,编译器会将所有的成员函数转换为C-Style的函数。为了实现这一操作,就需要将在add函数的第一个参数前插入this指针:将成员函数转换为非成员函数;

现在,第二个 val()函数被 const 修饰,那么,其 编译后的函数参数列表中的第一个参数就是 const Number *this ,因此,与 第一个 val() 函数在参数列表中不一致,可以重载。

即,上述两个成员函数会被 name mangling 为:

// 两个 add() 函数
_ZN6Number3valEv(Number* this);
_ZNK6Number3valEv(const Number* this);

那么此时,这两个参数列表就不一致了

补充:成员函数 被 const 修饰,此时这个成员函数是一个常函数;

           常函数内不可以修改成员属性

           非要修改的话只能如下示:修改的变量前加上 mutable 关键字

class Person 
{
    public:
	void ShowPerson() const
	{
		m_age = 100;
	
	}
	mutable int m_age;
};

补充一下:若 const 不是修饰的成员函数,只是修饰的 返回值

即: const int val() {return val_; } 这种还是会报错,重载失败

5. C语言中没有重载就是因为:

编译器不支持对 C语言 根据其参数列表进行 重命名,而且C语言中,对函数名字的编译方式风格与C++不同:
(1)C++中可以通过在函数声明前加 extern "C" 将一个函数按照 C 语言的风格来进行编译。

(2)C++想要调用已经编译过的C函数,由于编译过的名字不同,是不能直接调用的,所以C++加extern“C”生命来解决这个问题。

例如:假设某个函数的原型为: void foo(int x, int y);该函数被C 编译器编译后在库中的名字为_foo, 而C++ 编译器则会产生像_foo_int_int 之类的名字,加上extren”C”后,就相当于告诉编译器,函数foo是个C编译后的函数,在库里应该找的是_foo,而不是_foo_int_int.

你可能感兴趣的:(c++)