文章目录
- 1.域运算符
- 2.new、delete运算符
- 3.重载
- 4.name managling与extern “C”
- 5.带默认形参值的函数
- 6.带默认形参值的函数的二义性
1.域运算符
- C++中增加的作用域标识符 ::
(1)用于对与局部变量同名的全局变量进行访问
(2)用于表示类的成员,这将在关于类的一节中详细说明 - eg:
#include <iostream>
using namespace std;
int var = 100;
int main(void)
{
int var = 50;
cout<<var<<endl;//输出为50
cout<<::var<<endl;//输出为100
return 0;
}
2.new、delete运算符
- new运算符可以用于创建堆空间,类似c语言的malloc
- 成功返回首地址,失败抛出异常
- 语法:
指针变量=new 数据类型;//创建一个数据类型的长度
指针变量=new 数据类型[长度n];//创建n个数据类型的长度 - 例如:
int *p; p=new int;
char *pStr=new char[50];
- delete运算符 可以用于释放堆空间,与C语言的free类似
- 语法:
delete 指针变量;
delete [] 指针变量; - 例如:
delete p;
delete[] pStr;
- eg:
#include <iostream>
using namespace std;
int main(void)
{
int* p = new int; //分配一个整数空间
cout<<*p<<endl;//输出为任意值
int* p1 = new int(33); //分配一个整数空间4字节,初始值为33, ()表示只分配一个空间,对该空间进行初始化
cout<<*p1<<endl;//输出为33
int* p2 = new int[10]; //分配连续的10个整数空间 ,共40字节,[]表示分配连续的n个数据类型的空间
delete p;
delete[] p2;
return 0;
}
- new一个新对象(malloc只分配内存)
(1)内存分配(operator new)
(2)调用构造函数 - new的3种用法:
(1)new oprator:分配内存+调用构造函数
(2)operator new:只分配内存
(3)placement new:不分配内存,调用拷贝构造函数 - delete释放一个对象
(1)调用析构函数
(2)释放内存(operator delete)
3.重载
- 相同的作用域(这是前提!!),如果两个函数名称相同,而参数不同,我们把它们称为重载overload
- 函数重载又称为函数的多态性,是一种静态的多态,在编译时确定函数的入口地址,也称之为静态联编,动态的多态表现是派生类,基类是虚函数,在运行时确定函数入口地址,也称之为动态联编
- 函数重载不同形式(主要指:参数不同):
形参数量不同
形参类型不同
形参的顺序不同
形参数量和形参类型都不同 - 调用重载函数时,编译器通过检查实际参数的个数、类型和顺序来确定相应的被调用函数
- 合法的重载例子:
int abs(int i);
long abs(long l);
double abs(double d);
- 非法的重载例子:
int abs(int i);
long abs(int i);
void abs(int i);
//如果返回类型不同而函数名相同、形参也相同,则是不合法的,编译器会报"语法错误"。
4.name managling与extern “C”
- name managling这里把它翻译为名字改编。
如下eg所示,对于函数名都是fun而言,编译器所看到的函数名都不是一样的 - C++为了支持重载,需要进行name managling
- extern “C”实现C与C++混合编程
#ifdef __cpluscplus
extern “C”
{
#endif
...
#ifdef __cpluscplus
}
#endif
- eg:
#include <iostream>
using namespace std;
void fun(int a, int b)
{
cout<<"int fun"<<endl;
}
void fun(double a, double b)
{
cout<<"double fun"<<endl;
}
//extern "C"表示不进行名字改编,而按照C语言的方式解释函数名,就是不支持函数重载了
extern "c" void fun(int a)
{
cout<<"xxxx"<<endl;
}
#ifdef __cpluscplus //C++语言有定义该宏的,目的是为了可将下面的代码放置头文件中,让C++的程序也能被C语言使用
//extern "C"可以括起来多个函数
extern "C"
{
#endif
void fun(int a)
{
cout<<"xxxx"<<endl;
}
void fun2(double a)
{
cout<<"yyyy"<<endl;
}
#ifdef __cpluscplus
}
#endif
/*
若头文件是a.h,头文件只有函数声明,实现放在c++中,但是提供的头文件也可以被C语言所使用
#ifdef __cpluscplus
extern "C"
{
#endif
void fun(int a)
void fun2(double a)
#ifdef __cpluscplus
}
#endif
*/
int main(void)
{
fun(3,4);
fun(3.3, 4.4);
fun(3);
return 0;
}
- 进一步可参考:C调用C++和C++调用C
5.带默认形参值的函数
- 函数声明或者定义的时候,可以给形参赋一些默认值
- 调用函数时,若没有给出实参,则按指定的默认值进行工作
- 函数没有声明时,在函数定义中指定形参的默认值
- 函数既有定义又有声明时,声明时指定后,定义后就不能再指定默认值
- 默认值的定义必须遵守从右到左的顺序,如果某个形参没有默认值,则它左边的参数就不能有默认值。
void func1(int a, double b=4.5, int c=3); //合法
void func1(int a=1, double b, int c=3); //不合法
- 函数调用时,实参与形参按从左到右的顺序进行匹配
- eg:
#include <iostream>
using namespace std;
int fun(int a, int b=5)
{
return a + b;
}
int fun(int a, int b, int c);//声明给出默认值,定义的时候就不需要给默认值
int main(void)
{
cout<<fun(3)<<endl;//输出为8
cout<<fun(3, 4)<<endl;//输出为7
cout<<fun(3,4,5)<<endl;//输出为12
return 0;
}
int fun(int a, int b, int c)
{
return a + b + c;
}
6.带默认形参值的函数的二义性
- 重载的函数中如果形参带有默认值时,可能产生二义性
只有在不产生二义性的前提下,才可以采用带默认形参值的函数 - eg: sum=add(10,20)语句产生二义性性,可以认为该语句是调用第一个函数,也可以是第二个,因此编译器不能确定调用的是哪一个函数。
int add(int x=5, int y=6);
int add(int x=5, int y=6, int z=7);
int main() {
int sum;
sum= add(10,20);
return 0;
}
========================================================
int add(int x, int y)
{
return x+y;
}
int add(int x, int y, int z)
{
return x+y;
}