概述
C++基础讲解第一期 代码中也有对应知识注释,别忘看
- 一、面向对象概述
- 1、C++发展
- 2、为什么要学习C++
- 3、面向对象和面向过程
- 4、C++与C语言相比的改进
- 5、面向对象的三要素(中心思想)
- 二、C到C++的过度
- 1、第一个代码
- 2、作用域限定符(::)
- 3、命名空间
- a)目的:
- b)使用
- 4、C++的输入和输出
- 5、register关键词
- 6、struct的加强
- 7、bool类型
- 8、c与c++中三目运算符的不同
- 9、c/c++中的const:
- 10、C++引用
- a)概念:
- b)使用
- 11、引用的本质:常指针
- 12、引用作为函数的返回值
- 13、指针引用
- 14、常引用
- 15、内联函数
- 16、c++中的默认参数
- 17、占位参数
- 18、函数重载(重点)
- 19、c++的动态内存分配
- 20、多维数组的创建和释放
一、面向对象概述
1、C++发展
1998开始,c++98—>c++03—>c++11—>c++14
2、为什么要学习C++
众所周知,c++是一门面向对象的语言,在世界上的地位非常高,使用非常广泛,就业前景好。c++是c语言的升级版,c++几乎完全兼容c语言。
应用范围:应用软件开发、游戏开发、多媒体开发、人工智能、底层驱动、图形界面。
3、面向对象和面向过程
C语言:面向过程,以过程为中心,强调做算法,特点就是以函数为单位。数据从一个函数流向另一个函数。
C++:面向对象,是以事务为中心的编程,封装一个个的类,维护的代码期待更少。
4、C++与C语言相比的改进
C++是从C语言演化而来,C语言是过程式编程语言,以过程为中心,以算法为驱动。而C++是面向对象的编程方式,以对象为中心,以消息为驱动的编程方式,这是C++在C语言上的最大改进。
5、面向对象的三要素(中心思想)
封装:把一类事物抽象封装成类,并且可以把自己的类中的数据和函数只让可信的类或者对象操作。对不可暴露的接口进行隐藏。
继承:所谓继承,就是指类和类之间的关系,一个类可以继承另一个类
多态:多种形态,简单的说就是一个接口,多种方法,程序在运行的时候,才决定调用哪个函数。
二、C到C++的过度
1、第一个代码
#include<iostream>//C++标准输入输出流
using namespace std;//声明标准命名空间
int main(){
cout<<"hello world!"<<endl;//cout:标准输出函数 <<:输出运算符 endl:换行
}
2、作用域限定符(::)
#include<iostream>
using namespace std;
int num = 100;
int main(){
int num = 999;
cout<<"num ="<<num<<endl;//不加作用域运算符,因为在局部变量作用域中 所以输出的是局部变量num的值
//::作用域限定符,主要用于操作全局变量或者类或者函数
cout<<"num2 = "<<::num<<endl;//加上作用域运算符 输出的就是全局变量num
return 0;
}
3、命名空间
a)目的:
为了解决多个小组合作开发时,或者不同代码段之间命令冲突的问题,C++引入了命名空间的概念。
b)使用
1)语法
namespace Li
{
//变量、函数、类、宏定义等等
}
2)使用
#include<iostream>
/*命名空间:
命名空间里面几乎可以存放所有的全局的东西
例如:全局变量,函数,结构体,类,宏定义等
定义一个命名空间
注意:定义之后不需要加;
内部变量空间已经开辟,不只是定义数据类型
*/
using namespace std;
namespace zhangsan //命名空间zhangsan
{
int num = 333;
void fun()
{
cout<<"hello zhangsan"<<endl;
}
}
namespace Lisi //命名空间Lisi
{
int num = 888;
void fun()
{
cout<<"hello Lisi"<<endl;
}
}
void test()//命名空间使用方法一
{
cout<<"zahngsan的num = "<<zhangsan::num<<endl;
cout<<"lisi的num = "<<Lisi::num<<endl;
zhangsan::fun();
Lisi::fun();
//使用时都要在变量前加上命名空间和作用域限定符 来确定是哪一个变量
}
void test2()//命名空间使用方法二
{
using zhangsan::num;
//using Lisi::num; 不能同时对同名的其他命令空间的成员进行声明
cout<<"zhangsan的num = "<<num<<endl;
num = 1000;//将zhangsan中的num修改为1000
cout<<"zhangsan的num = "<<num<<endl;
cout<<"Lisi的num = "<<Lisi::num<<endl;
//使用lisi的num还和方法一一样 因为没有声明lisi的命名空间
}
//使用命名空间方法三
using namespace zhangsan;//与使用using namespace std 相同 先声明
void test3()
{
cout<<num<<endl;
}
int main(){
//test();
//test2();
test3();
return 0;
}
4、C++的输入和输出
输入:cin
输出:cout
#include<iostream>
using namespace std;
void test1(){
int a = 333;
char b = 'w';
char c[] = "hello";
float d = 3.1415926;
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"c = "<<c<<endl;
cout<<"d = "<<d<<endl;
}
void test2(){
int a,b,c;
cin>>a>>b>>c; //cin:标准输入函数 >>:输入运算符
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"c = "<<c<<endl;
}
int main(){
//test1();
test2();
return 0;
}
5、register关键词
register关键词的作用:请求编译器让变量存放在寄存器里面,以提升变量的访问速率。
C语言:register关键词修饰的变量不可以用&操作符取地址。内存的最小单位是字节,我们对内存的每个字节进行编号,这个编号就是我们所说的地址,寄存器不在内存之中,所以不能对其取地址。
C++:可以对一个寄存器变量取地址,但register对变量的声明变得无效,被定义的变量将会强制保存在内存中。
#include<iostream>
using namespace std;
int main(){
register int i = 0;//声明一个寄存器变量,不能取地址
register int j = 0;
for(i = 0;i < 10000;i++){
for(j = 0;j < 10000;j++){
}
}
cout<<"运行结束"<<endl;
return 0;
}
6、struct的加强
C++中的结构体
#include<iostream>
using namespace std;
int main(){
register int i = 0;//声明一个寄存器变量,不能取地址
register int j = 0;
for(i = 0;i < 10000;i++){
for(j = 0;j < 10000;j++){
}
}
cout<<"运行结束"<<endl;
return 0;
}
7、bool类型
C语言中想要判断“真”和“假”,只能用0和1来表示,这点在c++中加以改进,引入了两个新的关键词true和false
bool类型用法:
1.占一个字节
2.bool类型只有两个取值----true和false(编译器内部分别用1和0表示)
3.用途:推荐使用bool类型表示逻辑运算,关系运算以及开关变量的值。
#include<iostream>
using namespace std;
int main(){
bool a = true;
cout<<"a = "<<a<<endl;
bool b = false;
cout<<"b = "<<b<<endl;
bool c = -1;
cout<<"c = "<<c<<endl;
cout<<"sizeof(bool) = "<<sizeof(bool)<<endl;
return 0;
}
8、c与c++中三目运算符的不同
c语言:三目运算符返回的是变量的值
c++:三目运算符返回的是变量本身(可以作为左值使用)
#include<iostream>
using namespace std;
int main(){
int a = 1,b = 0;
int num = (a > b) ? a : b;
cout<<"num ="<<num<<endl;
(a < b) ? a : b = 100;
cout<<"b = "<<b<<endl;
return 0;
}
9、c/c++中的const:
(1)区别:
c语言:const修饰的是只读变量,但是可以通过修改地址来修改其值,不可以通过变量来修改。
c++:真正的常量,const常量会被编译器放入符号表中,类似于宏,不占用内存,符号表存储的是一系列键值对,编译器不会为const常量分配空间,但是我们对一个常量进行取地址时,操作系统会分配一段内存,并且用常量来填充。
#include<iostream>
using namespace std;
int main(int argc, char const *argv[])
{
const int a = 1;//c++中,const修饰的是常量,放在符号表
int *p = (int *)&a;//对const修饰的常量取地址,编译器会分配一段内存空间,存储常量的值
*p = 2;//并不会改变a的值,*p会开辟一段新的空间用来存放2
printf("a = %d,*p = %dn",a,*p);//a还是1,p是2
return 0;
}
const和#define的区别:
1.const有类型,可以进行编译器类型安全检查,#define无类型,不可进行类型检查
2.const有作用域,而#define不太重视作用域,作用域默认是从定义到文件结尾,如果定义在指定作用域下有效的常量,那么#define就不能用
10、C++引用
a)概念:
c++提供了给变量取别名的机制,那就是引用,引用是c++相对于c的扩充。
注意:typedef是对类型取别名,不能对变量进行重命名。
b)使用
引用的定义方式类似于指针,只是用&取代了*,语法格式:
&:在定义的时候表示引用
type &name = data;//其实就是将变量data取别名为name
#include<iostream>
using namespace std;
//传引用,引用作为函数参数,将实参和形参绑定在一起,指向用一份数据
void swap(int &x,int &y){//在c语言中 我们是定义的指针 传参传的是地址 而使用引用就不需要这样了
int temp = x;
x = y;
y = temp;
}
int main(int argc, char const *argv[])
{
int a = 100,b = 200;
cout<<"a = "<<a<<"b = "<<b<<endl;
swap(a,b);
cout<<"a = "<<a<<"b = "<<b<<endl;
int &c = a;//使用引用必须初始化
c = 1000;
cout<<"a = "<<a<<endl;
//int &d = 100; //不能用常量初始化引用
return 0;
}
11、引用的本质:常指针
1.本质
int &name = var; --------->int *const name = &var;
//当使用引用时不初始化,计算大小时,是当作指针来计算
//当初始化时,跟初始化的变量大小一致
从使用者角度看,引用会让人误以为只是一个别名,没有字节的存储空间,这其实是c++内部为了实用性而做的细节隐藏。
#include<iostream>
using namespace std;
struct test{
int &a;//因为没有初始化,其相当于一个常指针,大小占8个字节
int &b;
char &c;
};
struct test1
{
int a;
int b;
char c;
};
int main(){
int a = 1;
char c = 'c';
int &pa = a;
char &pc = c;
cout<<sizeof(pa)<<endl;
cout<<sizeof(pc)<<endl;
cout << "test1 size = " << sizeof(test1) << endl;//结果是12,因为int占4个字节,占满了所以char也分配4个字节
cout<<sizeof(test)<<endl;//结果是24,因为指针占8个字节,分析正常的语法现象时,当别名分析,分析奇怪的语法现象时,当常指针分析
return 0;
}
12、引用作为函数的返回值
1)引用作为函数的返回值时,不能返回局部数据(局部变量,局部对象,局部数组)的引用,可以返回一个全局变量或者静态全局、局部变量的引用。
2)使用方式:
a)不接受返回值
b)用一个普通变量接收函数的返回值,这时接收的是变量的值而不是变量的引用
c)用一个引用来解释函数的返回值,接收的是一个引用
d)当作左值来使用
#include<iostream>
using namespace std;
int g = 100;
int& fun()//返回引用
{
int x = 1;
return g;//不能返回x,因为x是局部变量,为社么局部变量不能返回呢,因为我们说过引用必须初始化,当我们使用引用去接这个返回值时,其是一个局部变量,这时候其的生命周期已经结束,内存空间已经释放,那么引用就接不到,也就无法初始化,就错了
}
int main()
{
fun();//不接收返回值
int a = fun();//用一个普通变量接收返回的引用
cout<<"a = "<<a<<endl;//a = 100,但是无法通过a去改变g的值
int &b = fun();//用一个引用取接收函数的返回值,接收的就是一个引用
b = 10000;
cout<<"g = "<<g<<endl;
fun() = 200; //当成左值使用,将200赋值给了g
cout<<"g = "<<g<<endl; //g = 200
cout<<"b = "<<b<<endl; //b = 200
return 0;
}
13、指针引用
#include<iostream>
#include<string.h>
using namespace std;
struct student
{
int id;
char name[32];
};
void getmemory(student *&ptr)//使用指针引用 就不用传二级指针了
{
ptr = (student *)malloc(sizeof(student));
if(ptr == NULL){
return;
}
ptr->id = 100;
strcpy(ptr->name,"张三");
}
int main()
{
student *ptr = NULL;
getmemory(ptr);
cout<<"id = "<<ptr->id<<" name = "<<ptr->name<<endl;
return 0;
}
14、常引用
1)概论:所谓常引用,是指不能通过引用来改变引用对象的值。
定义:const Type &name = var;
2)使用方法:
常引用初始化方法有两种:
a)用一个普通变量去初始化常引用,例如:
int a;
const int &b = a;//b是a的常引用,a和b代表了同一块内存空间,但不能通过b去修改a的值
b)用常量初始化常引用,例如:
const int &num = 100;
#include<iostream>
using namespace std;
int main()
{
int a = 1;
const int &b = a;//变量初始化常引用
//b = 200; 不可以通过b修改a的值
a = 200; //可以通过a去修改a的值
const int &pd = 200;//可以用常量初始化常引用,不是存在符号表之上,有内存空间
//pd++; //不可以通过pd修改pd的值
int *pc = (int *)&pd;
(*pc)++;
cout<<"pd = "<<pd<<endl;
return 0;
}
15、内联函数
1)函数调用:有时间和空间的开销,程序在执行的过程中,需要做一些工作,将实参,局部变量,返回地址,以及若干寄存器变量压入栈中才能执行函数的代码,函数体中,代码执行完毕,还要清理现场,将之前压入栈的数据都出栈。
2)c语言中,可以使用宏函数来消除函数调用的时空开销,编译器通过复制宏代码,省去参数入栈,出栈等操作,但是宏函数存在一些安全隐患,但是在效率上还是可取的。
a>宏函数的缺陷:
在复制代码时,容易出现意想不到的边际效应,例如:
#define MAX(a,b) (a) > (b) ? a : b
执行语句
int i = 2, j = 1;
result = MAX(i,j) + 2;//其会被替换成 (i) > (j) ? i : j + 2, 其返回的是j + 2了,就错了
b>使用宏,无法调试
c>使用宏,无法访问类的私有成员
3)c++中,关于宏函数,推出了一种更高效的方式,就是使用内联函数,在编译阶段将函数体进行替换,类似于c语言中的宏展开,这种在函数调用处直接嵌入函数体的函数称为内联函数,也称为内置函数
4)内联函数的使用:
#include<iostream>
using namespace std;
inline int mymax(int a,int b)//只需要在函数定义处增加关键词inline即可
{
return (a > b ? a : b);
}
int main()
{
int i = 1,j = 2;
int result = mymax(i,j);
cout<<result<<endl;
return 0;
}
5)内联函数的特点和限制
a)不能存在任何的循环语句
b)不能存在过多的条件判断语句
c)函数体不能过于庞大
d)不能对函数进行取地址操作
e)函数内联声明必须在调用语句之前
总结:
内联函数相对于普通函数,省去了函数调用时压栈出栈和返回等开销,因此,当函数体的开销远远大于压栈、出栈等开销时,内联函数将变得无意义。
16、c++中的默认参数
1)概念:
c++中,定义函数可以给形参指定一个默认值,在使用该函数时,如果没有给形参赋值,将使用这个值。
#include<iostream>
using namespace std;
int Add(int a,int b, int c = 0)
{
return a + b + c;
}
int Bdd(int a = 1,int b = 3,int c = 0)
{
return a + b + c;
}
//因为默认参数的定义顺序自左向右,如果设置了一个默认值,那么右边所有参数都要设置默认值
int Cdd(int a,int b = 3,int c = 4)
{
return a + b + c;
}
int main()
{
cout<<Add(1,2)<<endl;//第三个参数有了默认值,所以可以不用给形参赋值
cout<<Add(1,2,3)<<endl;//当然也可以赋值,如果赋值就使用 我赋的这个值 默认值就不使用了
cout<<Bdd(1,2)<<endl;//三个参数都要默认值,可以都不赋值
//cout<<Cdd(1,2)<<endl;
//使用错误,因为默认参数的定义顺序自左向右,如果设置了一个默认值,那么右边所有参数都要设置默认值
cout<<Cdd(1)<<endl;
return 0;
}
17、占位参数
1)概念:占位参数中有参数类型的声明,没有参数名的声明,一般情况下,在函数体内无法使用占位参数
#include<iostream>
using namespace std;
struct A
{
unsigned int a:10;//a占10位
unsigned int :22;//无名位域 占22位 没有名字 谁也使用不了
unsigned int c:2;//c占2位
//因为字节对齐 a分配了四个字节 32位 a占了10位
//还有22位没有使用 无名位域正好占用22位,所以前两个一共四个字节
//虽然c只占用2位 但由于字节对齐 其是int型 所以分配四个字节
//这个结构体一共占用8个字节
};
void Add(int a,int b,int = 0)//一般占位参数和默认参数一起使用
{
cout <<a + b<<endl;
}
int main(int argc, char const *argv[])
{
Add(1,2);
cout<<sizeof(A)<<endl;
return 0;
}
18、函数重载(重点)
1)概念:
在实际开发中,有时候需要实现几个功能类似的函数,只是有些细节不同,c语言中需要设计多个函数,而函数的重载解决了这个问题。
2)重载的条件(重点)
a)函数名相同
b)函数的参数的个数或者类型或者参数的顺序不同(注意:常量不能作为重载的标准)
c)返回值类型不能作为重载的标准
#include<iostream>
using namespace std;
void Swap(int &a,double &b)
{
cout<<"第一个"<<endl;
int tmp = a;
a = b;
b = tmp;
}
void Swap(int &a,int &b)//参数的类型不同
{
cout<<"第二个"<<endl;
int tmp = a;
a = b;
b = tmp;
}
void Swap(int &a,double &b,int c)//参数的个数不同
{
cout<<"第三个"<<endl;
int tmp = a;
a = b;
b = tmp;
}
void Swap(double &b,int &a)//参数的顺序不同
{
cout<<"第四个"<<endl;
int tmp = a;
a = b;
b = tmp;
}
int main()
{
int a = 1,c = 2;
double b = 1.111;
Swap(b,a);
return 0;
}
3)函数重载的二义性
#include<iostream>
using namespace std;
void Add(int a,int b)
{
cout<< a + b <<endl;
}
void Add(int a,int b,int c = 0)
{
cout<< a + b + c<<endl;
}
int main(int argc, char const *argv[])
{
//Add(1,2);区分不了使用哪个函数
return 0;
}
19、c++的动态内存分配
1)new和delete的基本用法
c语言:使用malloc和free函数
c++:malloc和free仍然可以使用,但是c++提供了专门的分配方式:new和delete
2)二者区别(重要)
c语言中:malloc和free是一个函数,函数值类型是(void*),不可以初始化
c++:new和delete是一个关键词,返回值类型为申请对象的类型,可以初始化
#include<iostream>
using namespace std;
int main()
{
int *p = new int;//分配了一个int类型的内存空间,返回值是(int *)
*p = 100;
cout<<"*p = "<<*p<<endl;
delete p;
p = NULL;
int *q = new int(200);//分配空间并初始化
cout<<"*q = "<<*q<<endl;
delete q;
q = NULL;
//c++11标准,c++11之前的版本不可以初始化动态数组
int *q2 = new int[5]{1,2,3,4,5};//分配五个int型,也就是分配个数组,里面五个int型,用()初始化
for(int i = 0;i < 5;i++)
{
cout<<q2[i]<<" ";//" "是加空格
}
cout<<endl;
delete []q2;//释放动态数组 需要加上[]
q2 = NULL;
return 0;
}
20、多维数组的创建和释放
例如:二维数组的动态创建,例如:申请二维数组int a[5][6];
#include<iostream>
using namespace std;
int main()
{
int **a = new int*[5];//分配一个二维数组,每个数组的元素是一个指针,指向一个一维数组
for(int i = 0;i < 5;i++)
{
a[i] = new int[6];//为一维数组分配空间
}
//使用delete来释放,只要将顺序反过来就行
for(int i = 0;i < 5;i++)
{
delete []a[i];
a[i] = NULL;
}
delete []a;
a = NULL;
return 0;
}
最后
以上就是自然信封为你收集整理的C++基础讲解第一期(超详细)一、面向对象概述二、C到C++的过度的全部内容,希望文章能够帮你解决C++基础讲解第一期(超详细)一、面向对象概述二、C到C++的过度所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复