目录
1、C++语言的概述:
c++语言特点:面向对象的编程语言。
俩大编程思想:面向对象、泛型编程。
三大特点:封装继承多态。
面向对象的思想,在c++中把问题抽象成类。类中有对象的属性和行为,属性又可以分为私有、公有和保护,类也可以实例化对象。
2、C++语言的三大特点:
(1)、封装
把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。类将成员变量和成员函数封装在类内部,根据需要设置访问权限,通过成员函数管理内部状态。
(2)、继承
继承所表达的是类之间相关的关系,这种关系使得对象可以继承另外一类对象的特征和能力。继承的作用:避免公用代码的重复开发,减少代码和数据冗余
(3)、多态
多态性可以简单地概括为“一个接口,多种方法”,字面意思为多种形态。程序在运行时才决定调用的函数,它是面向对象编程领域的核心概念。
3、c++对c的扩展:
(1)、::作用域运算符
1、::域控制符来解决,局部变量和全局变量重名的问题。
2、C++中的using namespace std使用std所在的命名空间,从而调用cout 和 endl。
(2)、命名空间定义
命名空间必须全局范围内定义
(3)、命名空间的嵌套
命名空间中可以嵌套一个命名空间。
(4)、无命名空间
限制了当前的命名空间只在当前文件起作用。
(5)、命名空间的成员的声明和实现可以分离
在全局区定义俩个相同名字的命名空间,相当于定义在一个空间中。
(6)、命名空间取别名
命名空间取别名不同于c中的结构体取别名
(7)、using声明
1、using声明可以使得指定的标识符可用。
2、using声明碰到函数重载要考虑,函数的参数个数,参数的类型,参数的顺序。不能把返回值做为函数重载的条件。
注意:如果声明中的命名空间中有多个相同名字的重载函数,则using可以声明这个重载函数的集合
(8)、using编译指令
using 编译指令使整个命名空间标识符可用
注意:使用 using 声明或 using 编译指令会增加命名冲突的可能性。也就是说,如果有名称空间,并在代码中使用作用域解析运算符,则不会出现二义性。
4、全局变量检测增强:
在c语言中如果代码如下,不会出现问题,会把一个当作定义,一个当作声明。
int a;//当做定义
int a//当作声明
在c++中会出现问题,需要写规范
int a;
extern int a;
5、C++中所有的变量和函数都必须有类型:
//在c语言中 i 没有写类型,可以是任意类型
int fun1(i)
{
printf("%d\n", i);
return 0;
}
调用时:
fun1(10); // 正确的
fun1("aaa"); // 错误
在C ++中这种写法是有问题的,i必须得有类型。
6、更严格的类型转换:
void test01()
{
char * str = (char *)malloc(100); //如果去掉类型转换将会报错
}
7、struct类型的增强 :
主要区别在C中结构体中不能定义函数,在C++中可以定义函数
8、新增bool类型:
bool类型只有俩个值,分别是true (1)和false (0)。
9、三目运算符增强:
在c语言中三目运算符只能作为右值,不能作为左值。
在C++中如果放在左边会先进行三目运算符,再将结果赋值给三目运算符的结果。
10、C++中的const:
(1)、在c中的cosnt修改常量
void test07()
{
const int a = 10;//在C中a是被分配空间并且有地址
const int *p = &a;
*p = 100;//在C中只有a的值被保护不可以修改,但是指针可以更改指向的地址
printf("a = %d\n", a);//a的值变成10
}
(2)、在C++中的const修改常量
void test05()
{
const int a = 10;//存放在符号常量表中,没有空间
int *p = (int *)&a;
*p = 100;
printf("a = %d\n", a);//a的值是10
}
(3)、C++中全局const
const int a = 10;//数据被保护,这段代码不能运行,不可修改
void test05()
{
int *p = (int *)&a;
*p = 100;
printf("a = %d\n", a);
}
(4)、C++中修改const变量
void test01(){
int a = 10;
const int b = a;
int *p = (int *)&b;
*p = 200;
cout <<"b = " << b <<"*p = "<< *p << endl;
//结果 都是200
}
(5)、在C++中用const来替换掉#define
1、 const 有类型,可进行编译器类型安全检查。 #define 无类型,不可进行类型检查。
2.、const 有作用域,而#define 不重视作用域,默认定义处到文件结尾.如果定义在指定作用域下有效的常量,那么#define 就不能用。
11、引用:
注意事项:
1. &在此不是求地址运算,而是起标识作用
2. 类型标识符是指目标变量的类型
3. 必须在声明引用变量时进行初始化
4.引用初始化之后不能改变.
5.不能有 NULL 引用,必须确保引用是和一块合法的存储单元关联.
(1)、数组引用的定义和使用
#include <iostream>
using namespace std;
void test01(){
int arr[5] ={1,2,3,4,5};
int(&myarr)[5] = arr;//引用定义一个数组
cout<<myarr[0]<<myarr[1]<<myarr[2]<<myarr[3]<<myarr[4]<<endl;
}
int main(int argc, char *argv[])
{
test01();
return 0;
}
(2)、给指针变量取别名
#include <iostream>
using namespace std;
void test01()
{
int num = 10;
int *p = #
int *&q = p;//指针p取别名为q
cout<<*p<<" "<<*q<<endl;
}
int main(int argc, char *argv[])
{
test01();
return 0;
}
(3)、给函数取别名
#include <iostream>
using namespace std;
void func(int a){
cout<<a<<endl;
}
void test01()
{
using FUN = void(&)(int);
//声明一个引用类型的别名FUN指向参数为int类型函数
FUN newfunc = func;
//然后用别名定义一个函数指向func
newfunc(10);
}
int main(int argc, char *argv[])
{
test01();
return 0;
}
(4)、引用作为函数的参数
#include <iostream>
using namespace std;
void func( int &a)
{
//引用相当于操作a的内存,而不是赋值一个新的
a = 100;
}
void test01()
{
int a = 0;
func(a);
cout<<a<<endl;
}
int main(int argc, char *argv[])
{
test01();
return 0;
}
(5)、引用作为函数的返回值
#include <iostream>
using namespace std;
int &func()
{
//返回值类型是引用类型
int a = 100;
int &b =a;
//不能直接返回a,只能返回引用。
return b;
}
void test01()
{
int &ret =func();
//返回的是引用只能用引用来接收
cout<<ret<<endl;
}
int main(int argc, char *argv[])
{
test01();
return 0;
}
(6)、引用实现链式操作
#include <iostream>
using namespace std;
struct Print
{
Print &func(Print &obj, char *str){
cout<< str <<endl;
return obj;
}
};
void test01()
{
Print ob;
ob.func(ob,"haha").func(ob,"lala").func(ob,"hehe");
}
int main(int argc, char *argv[])
{
test01();
return 0;
}
(7)、常量引用
常量引用作为引用或者函数参数都不允许修改。
#include <iostream>
using namespace std;
void test02(const int &num)
{
num = 10;//不能修改
}
void test01()
{
int a = 10;
const int &b = a;
b = 100;//不能修改
test02(a);
}
int main(int argc, char *argv[])
{
test01();
return 0;
}
引用本质就是一个指针常量,所以初始化只会不可以再进行修改引用本身的地址。
(8)、引用的大小
引用的大小由指向的类型决定
12、内联函数的定义:
注意:
1. 必须函数体和声明结合在一起,否则编译器将它作为普通函数来对待。
2. 任何在类内部定义的函数自动成为内联函数。
3.不能存在任何形式的循环语句
4 。不能存在过多的条件判断语句
5.函数体不能过于庞大
6.不能对函数进行取址操作
13、宏函数和内联函数的区别:
(1)、宏函数:
1、参数没有类型 不能保证参数的完整型。
2、宏函数 在预处理阶段 展开。
3、宏函数 没有作用域限制 不能作为类的成员。
(2)、内联函数:
1、参数有类型 能够保证参数的完整型。
2、宏函数 在编译阶段 展开。
3、内联函数 有作用域限制 能作为类的成员。
14、函数的默认参数:
c++在声明函数原型的时候可为一个或者多个参数指定默认(缺省)的参数值,当函数调用的时候如果没有指定这个值,编译器会自动用默认值代替。
(1)、设置默认参数的规定
如果某个形参 设置默认参数值,那么后面位置的形参也需要设置默认参数(从右向左设置)。
(2)、函数的占位参数
15、extern"C"
extern "C"的主要作用就是为了实现 c++代码能够调用其他 c 语言代码。加上extern "C"后,这部分代码编译器按 c 语言的方式进行编译和链接,而不是按 c++的方式。
#include <iostream>
extern "C" int add(int,int);//使用C的函数约定,告诉编译器按照C函数约定调用
#ifndef __cplusplus //如果不是C++编译器就声明C
extern"C"{
#endif
//声明
//声明
//声明
#ifndef __cplusplus
}
#endif