1 什么是面向对象】
概念上来说:就是以对象(具体的变量)为导向的编程思路
专注于:一个对象具体能实现哪些过程(哪些功能)
面向对象 = n * 面向过程
结论:面向对象需要做的事情
1:我们要想清楚,我们现在需要编写一个拥有哪些功能的对象 (面向对象的思路,C++编程)
2:再去为这个对象中的每一个功能做具体的实现(实际就是面向过程,c语言编程)
2 c++与c语言的一些区别
2.1 字符串类型
c语言的字符串,就是字符数组,不是一个变量
c++的字符串,就是一个变量
既然是变量,c++ 字符串就允许做以下的操作
string str = "123"
string ptr = "456"
str = ptr;
str == ptr;
str += ptr;
将c++字符串转换成c语言字符串(将string转换成const char* 类型)
const char* s = str.data();
2.2 bool 类型
bool 类型的变量只有2个值:
true 或者 false
其实还是 1 和 0,1表示真,即true,0表示假,即false
c++ 专门搞了个数据类型来表示 真或者假
2.3 标准输入输出
c语言标准输出:printf c语言标准输入:scanf
c++ 的标准输出:cout c++ 的标准输入:cin
2.4 auto 关键字
c语言中的auto:自动申请局部变量的意思,现代编译器基本都省略
c++中的auto:自动推导类型
例如:
auto a = 100
则会将a推到成int类型
auto b = 3.14
自动将b推到成double类型
。。。。
其实就是根据 = 右侧的数据类型,自动推导 = 左侧的变量的类型
2.5 引用
引用的写法
int a = 10;
int& pa = a;
引用,本质上来说就是一个变量的别名、别称
当我们输出 pa 和 a (即一个引用和被改引用绑定的变量地址)的话
我们会发现2个地址是一模一样的
既然地址一样,就说明是同一个变量
既然是同一个变量,改a,pa会变,改pa ,a也会变
引用的特点
1:引用一旦绑定一个数据之后,就无法更换绑定了,永远与该数据绑定在一起
2:由于引用无法中途更换绑定对象,所以引用必须初始化,如果没有初始化,后续也没有机会为他绑定数据了
3:常量只能被常量引用绑定,但是反过来,变量即可以被普通引用绑定,也可以被常量引用绑定
引用和指针的区别
1:指针拥有一个独立的地址,地址上存放的是被指向的数据的地址
引用无法获取引用本身的地址,引用的地址即为变量的地址
2:指针中途允许随意改变指向
引用中途不能更改绑定
3:指针可以不初始化,也可以初始化为空
引用必须初始化,绑定一个具体数据
4:sizeof 指针 大小是 4或者8
sizeof 引用大小取决于被绑定的数据的类型
4 c++的第一个程序:输出hello world
#include <iostream>
using namespace std;
int main(){
cout << "hello world" << endl;
return 0;
}
4.1 c++的头文件
c语言头文件的风格: #include <XXXX.h> 以.h结尾
c++头文件风格:#include <XXXX> 或者 #include <XXX.hpp>
早期开发c++的时候,c++ 为了统一c语言中的各种头文件风格,专门将c语言中的各种头文件,重新写了一遍
例如:将 stdio.h 写成了 cstdio,string.h 写成了 cstring
统一的将几乎所有 c语言的头文件 前面加上 c,后面去掉.h
即 xxx.h 改成了 cxxx
但是这个事情虎头蛇尾了,后面也没人提这个标准了
但是有一些代码还是会看见诸如
#include <cstring>
#include <ctime>
这样的头文件,大家要反应过来,这是c语言的头文件
4.2 using namespace std:命名空间
命名空间用途:防止多个程序在分模块开发的时候,写出同名结构体定义 和 同名函数的问题
4.2.1 如何声明一个命名空间
namespace 命名空间名{
写 结构体的自定义
函数的声明
函数的声明及定义
全局变量声明
全局变量的声明及定义
};
4.2.2 如何使用指定的命名空间]
1 在一个作用域里面,写上代码:using namespace 命名空间名
在写有该语句的作用域当中,都会额外的去目标命名空间中 查询函数/结构体名/全局变量
namespace zs{
void func(){
cout << "张三的func" << endl;
}
};
namespace ls{
void func(){
cout << "李四的func" << endl;
}
}
/*
void func(){
cout << "全局的func" << endl;
}
*/
int main(int argc,const char** argv){
using namespace zs;// 说明:在main函数作用域中,所有的函数名,结构体名,全局变量名,都会 "额外" 的再去 命名空间 zs 中寻找一遍
using namespace ls;
func();
}
所以,using namespace 这种形式,简单是简单,但是很不好用
非常容易造成冲突
2 在一个作用域里面写上:using 命名空间名::函数名/结构体名/全局变量名
namespace zs{
void func(){
cout << "张三的func" << endl;
}
struct Data{
int a;
};
};
namespace ls{
void func(){
cout << "李四的func" << endl;
}
struct Data{
double a;
};
};
void func(){
cout << "全局的func" << endl;
}
int main(int argc,const char** argv){
using zs::func;// 表明在当前作用域中,仅指定fun去zs命名空间中寻找,其他所有内容还是全局寻找
func();// 所以此处即使全局也有一个func,因为通过上面的代码指定了func只去zs中寻找,所以不报错
}
但是这种写法虽然比 using namespace 要好一点,依旧容易冲突
using zs::func
using ls::func
一眼报错
3 直接在函数名/结构体名/全局变量名前面加上 "命名空间名::"
zs::func()
表示调用 zs里面的func
ls::func()
表示调用ls里面的func
func()
表示调用全局的func
这种方式是最安全最常用的方式
4.2.3 :: 是什么东西
:: 是作用于运算符
例如 x::y
表明:使用y的时候(y可以是函数,结构体名,全局变量名),去x作用域中寻找y
也可以表明,y是隶属于x作用域的