一、C++在C基础上的新增特性
C++不是一门新的语言,而是在C基础上做了完善和扩充
(1)、更为严格的类型检查
在C语言中,小转大的隐性类型转化(如char->int)在编译时会报警告。而在C++中则会直接出错。
(2)、新增变量引用(给变量取别名)
int a = 123;
int &b = a;
printf("%d %d %p %p\n",a,b,&a,&b);
给a取别名为b,a与b的值和地址都相同,相当于给a创建了一个快捷方式b,且指向a的地址(引用只能初始化)
函数的引用传参
int fun(int &a,int &b)
{
return a+b;
}
int main()
{
int m = 10;
int n = 20;
fun(m,n);
return 0;
}
函数形参前面加上”&“,在传参时相当于int &a = int m,意味着给实参m取别名a。相较于值传参和地址传参等需要拷贝,引用传参效率更高。
(3)支持面向对象
新增了类类型和类、对象、继承、多态、虚函数、RTTI(运行时类型识别)等概念
类包含了对象的属性和方法类似于人的属性和行为
通过类定义对象
子类可以继承父类的方法并且可以修改不适合的方法(继承和多态、虚函数)
(4)新增了泛型编程(编写与类型无关的代码)
支持模板,C++中有标准模板库(STL)
template <class T>
T add(T a, T b)
{
return a+b;
}
使用时在函数前声明模板参数类型,函数中的类型可用模板参数代替
(5)支持异常处理
(6)支持函数及运算符重载
int add(int a)
{
return a+a;
}
int add(int a,int b)
{
return a+b;
}
char add(char x ,char y)
{
return x+y;
}
int main()
{
add(10);//int add(int a)
add(123,456);//int add(int a,int b)
add('a','b');//char add(char x,char y)
return 0;
}
函数重载指在同一个作用域,同名函数的参数不同(参数个数、参数类型,参数个数和类型都不相同),此时编译器会根据给函数的传递的不同实参调用相应的函数。与返回值无关。
运算符重载指对例如+、-、*、/等基本运算符只能对基本类型使用,我们通过某个方法使他们能对对象使用。
(7)支持名字空间(用于管理函数名、变量名及类)
名字空间有自己的作用域。不同名字空间可以定义相同的函数名和变量。
二、C和C++兼容及差异
C++源文件扩展名:*.cpp
引用头文件:新式风格 例如:#include <iostream> (不加.h)
(1)const变量
C++中不允许const向非const隐型类型转化,编译时会报错。而C只会报警告。
(2)强制类型转化
C++中强制类型转化为 新类型 (表达式)
int a;
char ch = char (a);
将变量a转化为char型再赋值给ch
(3)内联函数
在编译时,将函数代码直接嵌入到主调函数中,可以提高运行效率,但是会增加目标代码长度。适合用于多次重复使用的函数。在类中定义的函数也属于内联函数。内联函数语句条数要不大于五条,不能使用控制语句如循环或Switch语句。
inline 返回值类型 函数名 (形参列表);
(4)默认参数
函数可以在声明给形参设置默认参数。若给其中一个参数指定了默认值,则此参数后边所有参数都要指定默认值。若给有默认值的参数传递了实参,则形参的值为实参值,即实参值覆盖默认值。函数重载与默认参数一起容易发生歧义(无法避免,只能使用前好好设计)。
int add(int a)
{
return a+a;
}
int add(int a,int b=0)
{
return a+b;
}
int main()
{
add(10);
return 0;
}
当实参只有一个参数时,此时会发生歧义,编译器发现两个函数都适合,无法判断用户想要调用哪一个函数。
(5)结构体
struct Demo
{
public:
void setval(int value)
{
val = value;
}
int getval()
{
return val;
}
private:
int val;
};
C++中结构体可以有函数,默认是在公有权限,与类相反。public:公有权限,可以通过结构体变量直接访问 protected:保护权限,只能在内部或子类内部访问 private:私有权限:只能在成员函数访问,不可以通过结构体变量直接访问
三、作用域
c++中作用域有四个
(1)局部域:局部变量的作用域
(2)全局域:全局变量的作用域
(3)名字空间域:
namespace 名字空间名称{
变量;
函数;
类;
}
使用有两种方法:1、声明后直接使用 2、不声明直接使用
namespace A
{
int i = 123;
void prnmsg()
{
printf("hello world\n");
}
}
namespace B
{
int i = 123;
void prnmsg()
{
printf("hello world\n");
}
}
using namespace A;
cout << i << endl;
prnmsg();
cout << B::i << endl;
B::prnmsg();
(4)类域
class Demo
{
public:
void setval(int val)
{
myval = val;
}
private:
int myval;
};
类域与结构体类似,不过,默认权限为私有权限。
四、链接性及存储性
(1)变量的存储性和链接性
auto存储类型修饰的变量在函数模块内部声明,作用域也是整个函数模块,无链接性
register存储类型修饰的变量也在函数模块内部声明,作用域是整个函数模块,无链接性,此为寄存器存储,与cpu更近,访问速度快
全局变量时在函数外声明,作用域是整个程序文件,可以被外部程序文件用extern链接
用static修饰的全局变量与之前的区别在于只能在本文件链接不能用于外部文件链接
用static修饰的局部变量链接性也为空,作用域在函数模块内,因为局部变量都是运行时存在,所以无链接性。
(2)函数的链接性
非static函数:外部链接
static函数:内部链接
(3)语言链接性
C++中可以通过extern调用c语言的函数
main.cpp:
include <iostream>
extern "C" void prnmsg(const char *)
int main()
{
prnmsg("hello world");
return 0;
}
prnmsg.c:
void prnmsg(const char *str)
{
printf("%s\n",str);
}
五、动态内存
在堆区申请空间及释放空间
using namespace std;
int main()
{
int *p = new int ;//在堆区申请空间,定义指针指向该片地址空间
*p = 123;
cout << *p << endl;
delete p;//释放空间
int *q = new int [10];//在堆区申请一片空间
delete [] q;//释放空间
return 0;
}