day01 C++基础
1. 面向与面向过程的区别(重点)
我是一个菜鸡,这件事我一定要做完
#include "iostream" //包含c++的头文件 //iostream.h
using namespace std; //使用命名空间 std 标准的命名空间 (在这个命名空间中定义了很多标准定义)
//求圆的面积
//用面向过程的方法求解圆形的面积
// << >> 不会用: 标准输入cin和标准输出cout 始终写在操作符的左边
void main02()
{
double r = 0;
double s = 0;
cout << "请输入圆形的半径:";
//cin 标准输入 代表键盘
cin >> r;
cout << "r的值是:" << r << endl;
s = 3.14 * r * r;
cout << "圆形的面积是s:" << s << endl;
system("pause"); //不让屏幕一闪而过
}
//在C++中 定义了一个自定义数据类型 MyCicle 圆形
class MyCicle
{
public:
double m_s; //圆的面积 属性 成员变量
double m_r; //圆的半径
public:
void setR(double r) //成员函数
{
m_r = r;
}
double getR() //成员函数
{
return m_r;
}
double getS()
{
m_s = 3.14 * m_r * m_r;
return m_s;
}
};
//
void main03()
{
MyCicle c1, c2, c3; //用类 定义 变量 对象
double r;
cout << "请输入c1圆形的半径:";
cin >> r;
//给c1圆形的属性赋值
c1.setR(r);
cout << "c1圆形的面积是:" << c1.getS() << endl;
system("pause");
}
void main()
{
MyCicle c1, c2, c3; //用类 定义 变量 对象
double r1, r2, r3;
//圆形1
cout << "请输入c1圆形的半径r1:";
cin >> r1;
//给c1圆形的属性赋值
c1.setR(r1);
cout << "c1圆形的面积是:" << c1.getS() << endl;
//圆形2
cout << "请输入c2圆形的半径r2:";
cin >> r2;
//给c1圆形的属性赋值
c2.setR(r2);
cout << "c2圆形的面积是:" << c2.getS() << endl;
//圆形3
cout << "请输入c3圆形的半径r3:";
cin >> r3;
//给c3圆形的属性
c3.setR(r3);
cout << "c3圆形的面积是:" << c3.getS() << endl;
system("pause");
}
用面向对象的方法
- 类的抽象 成员变量和成员函数
- 实例化 类的对象
- 求面积 面向过程加工的是 一个一个的函数 面向对象加工的是:一个一个的类
- main集成测试
思考1:类的调用 执行过程分析==>类代码不是一步一步指向
类是一个数据类型,(固定大小内存块的别名); 定义一个类,是一个抽象的概念,不会给你分配内存
用数据类型定义变量的时候,才会分配内存,如下图所示。
思考2:抛砖: c++编译器是如何处理 多个对象,调用类的成员函数的;具体一点:如何区分是c1 c2 c3 调用了getS,抛砖…
2. C++对C的增强
2.1命名空间namespace的增强
#include "iostream"
using namespace std;
//1文件中iostream 没有引入标准的 std ; 需要我们程序员手工的写
//2 如果不写 using namespace std; 需要显示的引入std
void main31()
{
std::cout<<"namespace test"<<std::endl;
system("pause");
}
//3 定义命名空间
namespace namespaceA
{
int a = 10;
}
namespace namespaceB
{
int a = 20;
namespace namespaceC
{
struct Teacher
{
char name[32];
int age ;
};
}
}
//4 使用命名空间
//
void main()
{
using namespace namespaceA;
using namespace namespaceB;
cout<<namespaceA::a<<endl;
cout<<namespaceB::a<<endl;
//显示的, 写全
{
//namespaceB::namespaceC::Teacher t1;
//t1.age = 33;
}
//
using namespaceB::namespaceC::Teacher ;
Teacher t2;
t2.age = 36;
system("pause");
}
2.2实用性、Rigster关键字和检测类型的增强
#include <iostream>
using namespace std;
//C语言中的变量都必须在作用域开始的位置定义!!
//C++中更强调语言的“实用性”,所有的变量都可以在需要使用时再定义。
void main41()
{
int i;
printf("hello...\n");
int k;
i = 10;
k = 11;
printf("i:%d k:%d \n", i, k);
system("pause");
}
void main42()
{
register int a = 0;
printf("&a: %d \n", &a); //不能在寄存器变量上取地址
for (int i=0; i<1000; i++) //不使用register也可能做优化
{
printf("i:%d \n", i);
}
system("pause");
}
/*
在C语言中,重复定义多个同名的全局变量是合法的
在C++中,不允许定义多个同名的全局变量
C语言中多个同名的全局变量最终会被链接到全局数据区的同一个地址空间上
int g_var;
int g_var = 1;
C++直接拒绝这种二义性的做法。
*/
int g_a = 100;
//int g_a ;
void main()
{
printf("hello...g_a:%d \n", g_a);
}
2.3 struct结构的增强
#include <iostream>
using namespace std;
//struct 关键字 class关键字 完成的功能是一样的
//区别后面介绍 抛砖
class c1
{
public:
protected:
private:
};
struct Teacher
{
public:
char name[32];
int age;
protected:
int a;
};
void main51()
{
Teacher t1; //
t1.age = 10;
printf("hello...\n");
system("pause");
}
/*
C++中所有的变量和函数都必须有类型
C语言中的默认类型在C++中是不合法的
函数f的返回值是什么类型,参数又是什么类型?
函数g可以接受多少个参数?
*/
/*
//更换成.cpp试试
f(i)
{
printf("i = %d\n", i);
}
g()
{
return 5;
}
int main(int argc, char *argv[])
{
f(10);
printf("g() = %d\n", g(1, 2, 3, 4, 5));
getchar();
return 0;
}
*/
2.4增加bool数据类型
#include <iostream>
using namespace std;
void main()
{
bool b1 = true; //告诉c++编译器给我分配 1个字节的内存
bool b2, b3, b4, b5;
//
cout<<"sizeof(bool)"<<sizeof(bool)<<endl;
//bool变量 1 或者 0
b1 = 10;
cout<<"bl:" <<b1<<endl;
//bool变量 1 或者 0
b1 = -10;
cout<<"bl:" <<b1<<endl;
//bool变量 1 或者 0
b1 = 0;
cout<<"bl:" <<b1<<endl;
cout<<"hello..."<<endl;
system("pause");
return ;
}
2.5 对三目运算符功能的增强(重点)
#include <iostream>
using namespace std;
//在C语言中 表达式的结果 放在什么地方 寄存器
//1
// 在C语言中, 表达式的返回值 是变量的值
// 在C++中, 表达式返回的是变量的本身
//2 如何做到的
//让表达式返回一个内存空间 ..内存首地址 指针
//在C语言中 如何 实现 c++的效果
//3 本质
//c++编译器 帮我们程序员完成了 取地址的工作
int main()
{
int a = 10;
int b = 20;
int var = 100;
var = 101;
//返回一个最小数 并且给最小数赋值成3
//三目运算符是一个表达式 ,表达式不可能做左值
(a < b ? a : b )= 30;
//int z = (a < b ? a : b );
printf("a = %d, b = %d\n", a, b);
system("pause");
return 0;
}
2.5 C++中的const(重点)
#include <iostream>
using namespace std;
//0 const的基础知识
struct Teacher
{
char name[64];
int age;
};
//指针所指向的内存空间,不能被修改
int operatorTeacher01(const Teacher *pT)
{
//pT->age = 10;
return 0;
}
//指针变量本身不能被修改
int operatorTeacher02( Teacher * const pT)
{
pT->age = 10;
//pT = NULL; //
return 0;
}
int operatorTeacher03( const Teacher * const pT)
{
//pT->age = 10;
//pT = NULL; //
printf("age:%d", pT->age);
return 0;
}
void main81()
{
// const int a;
// int const b; //一样
//
// const int *c; //const修饰的是指针所指向的内存空间,不能被修改
// int * const d; //
// const int * const e ;
cout<<"hello..."<<endl;
Teacher t1;
t1.age = 33;
operatorTeacher03(&t1);
system("pause");
return ;
}
//1
//c语言中的const是一个冒牌货
//C++语言中 const是一个真正的常量
//2 原因分析
//const int b = 10; 符号表
void main82()
{
//好像 a 是一个常量
const int a = 10;
//a = 11;
int *p = NULL;
p = (int *)&a;
*p = 20; //间接赋值
printf("a:%d \n", a);
printf("*p:%d \n", *p);
system("pause");
}
//3 const分配内存的时机 编译器编译器期间
void main83()
{
//好像 a 是一个常量
int a;
const int b = 10;
int c;
printf("&a:%d, &b:%d, &c:%d \n", &a, &b, &c);
system("pause");
}
//4const 和 #define的相同之处
//#define, 在编译预处理阶段 处理
//const常量是由编译器处理的,提供类型检查和作用域检查
#define d 20
void main84()
{
//int a = 10;
//int b = 20;
//int array[a+b]; //linux内核里面是成立的;原因 编译linux内核的gcc编译器支持.
//c和c++编译器 不支持这种语法现象
const int c = 10;
//const int d = 20;
int array2[c+d];
system("pause");
}
//5 const定义的变量,由编译器处理的,提供类型检查和作用域检查
void fun1()
{
#define a 10
const int b = 20;
//#undef a
//# undef
}
void fun2()
{
printf("a = %d\n", a);
printf("b = %d\n", b);
}
int main()
{
fun1();
fun2();
return 0;
}
图片描述const过程
3. 引用专题讲解
3.1复杂数据类型的引用
#include <iostream>
using namespace std;
//1 引用的概念
//2 属于C++编译器对C的扩展,不能用c语言的语法去思考它
void main91()
{
int a = 10;
//引用的语法:Type& name = var;
int &b = a;
b = 100; //相当于把a修改成100了.
printf("b:%d \n", b);
printf("a:%d \n", a);
a = 200;
printf("b:%d \n", b);
printf("a:%d \n", a);
cout<<"hello..."<<endl;
system("pause");
return ;
}
void main92()
{
int a = 10;
int &b = a;
//int &c ; //03普通引用 必须要初始化
system("pause");
}
//基础类型的引用
void myswap(int a, int b)
{
int c = 0;
c = a;
a = b;
b = c;
}
void myswap02(int *a, int *b)
{
int c = 0;
c = *a;
*a = *b;
*b = c;
}
//04 引用作为函数参数声明时不进行初始化
void myswap03(int &a, int &b)
{
int c = 0;
c = a;
a = b;
b = c;
}
void main93()
{
int x, y ;
x = 10;
y = 20;
myswap(x, y);
printf("x:%d , y:%d \n", x, y);
myswap02(&x, &y);
printf("x:%d , y:%d \n", x, y);
//a就是x的别名 b就是y的别名
myswap03(x, y);
printf("x:%d , y:%d \n", x, y);
//int &c ; //普通引用 必须要初始化
system("pause");
}
//05复杂数据类型 的引用
struct Teacher
{
char name[64];
int age ;
};
void printfT(Teacher *pT)
{
cout<<pT->age<<endl;
}
//pT是t1的别名 ,相当于修改了t1
void printfT2(Teacher &pT)
{
//cout<<pT.age<<endl;
pT.age = 33;
}
//pT和t1的是两个不同的变量
void printfT3(Teacher pT)
{
cout<<pT.age<<endl;
pT.age = 45; //只会修改pT变量 ,不会修改t1变量
}
void main()
{
Teacher t1;
t1.age = 35;
printfT(&t1);
printfT2(t1); //pT是t1的别名
printf("t1.age:%d \n", t1.age); //33
printfT3(t1) ;// pT是形参 ,t1 copy一份数据 给pT //---> pT = t1
printf("t1.age:%d \n", t1.age); //35
cout<<"hello..."<<endl;
system("pause");
return ;
}
3.2 引用的本质
#include <iostream>
using namespace std;
//1 第一点 单独定义的引用时,必须初始化;说明很像一个常量
void main01()
{
//
const int c1 = 10;
int a = 10;
int &b = a; //b很想一个常量
printf("&a:%d \n", &a);
printf("&b:%d \n", &b); //===> a 和 b就是同一块内存空间的门牌号
cout<<"hello..."<<endl;
system("pause");
return ;
}
//2 普通引用有自己的空间吗? 有
struct Teacher
{
char name[64]; //64
int age; //4
int &a; //4 0 //很像指针 所占的内存空间大小
int &b; //4 0
};
//3 引用的本质
void modifyA(int &a1)
{
a1 = 100;
}
void modifyA2(int * const a1)
{
*a1 = 200; //*实参的地址 ,去间接的修改实参的值
}
void main1001()
{
int a = 10;
//1
modifyA(a); //指向这个函数调用的时候,我们程序员不需要取a的地址
printf("a:%d \n", a);
//
a = 10;
modifyA2(&a); //如果是指针 需要我们程序员手工的取实参的地址
printf("a:%d \n", a);
printf("sizeof(Teacher):%d \n", sizeof(Teacher));
system("pause");
}
void modifyA3(int *p)
{
*p = 200; //*p 3*p形参去间接修改实参的值
}
//间接赋值
void main()
{
int a = 10;
int *p = NULL; //间接赋值成立的三个条件 1 定义两个变量
p = &a;
*p = 100;
{
*p = 200;
}
modifyA3(&a); //2 建立关联
}
// 123 写在一块
// 12 3
//1 23
3.3 引用的难点,返回值的引用
#include <iostream>
using namespace std;
int getAA1()
{
int a ;
a = 10;
return a;
}
//返回a的本身 返回a的一个副本 10
int& getAA2()
{
int a ; //如果返回栈上的 引用, 有可能会有问题
a = 10;
return a;
}
int* getAA3()
{
int a ;
a = 10;
return &a;
}
void main1101()
{
int a1 = 0;
int a2 = 0;
a1 = getAA1();
a2 = getAA2(); //10
int &a3 = getAA2(); //若返回栈变量 不能成为其它引用的初始值
printf("a1:%d \n", a1);
printf("a2:%d \n", a2);
printf("a3:%d \n", a3); // *a3
cout<<"hello..."<<endl;
system("pause");
return ;
}
//变量是static 或者是 全局变量
int j1()
{
static int a = 10;
a ++ ;
return a;
}
int& j2()
{
static int a = 10;
a ++ ;
return a;
}
//若返回静态变量或全局变量
// 可以成为其他引用的初始值
// 即可作为右值使用,也可作为左值使用
void main1112()
{
int a1 = 10;
int a2 = 20;
a1 = j1();
a2 = j2();
int &a3 = j2();
printf("a1:%d \n", a1);
printf("a2:%d \n", a2);
printf("a3:%d \n", a3);
system("pause");
}
//
//--- 函数当左值
//返回变量的值
int g1()
{
static int a = 10;
a ++ ;
return a; //
}
//返回变量本身 ,
int& g2()
{
static int a = 10;
a ++ ;
printf("a:%d \n" , a);
return a;
}
void main()
{
// g1() = 100;
//11 = 100;
g2() = 100; //函数返回值是一个引用,并且当左值
g2();
int c1 = g1(); //函数返回值是一个引用,并且当右值
int c2 = g2(); //函数返回值是一个引用,并且当右值
//a = 100;
system("pause");
}
3.4 指针的引用
#include "iostream"
using namespace std;
//
struct Teacher
{
char name[64];
int age ;
};
//在被调用函数 获取资源
int getTeacher(Teacher **p)
{
Teacher *tmp = NULL;
if (p == NULL)
{
return -1;
}
tmp = (Teacher *)malloc(sizeof(Teacher));
if (tmp == NULL)
{
return -2;
}
tmp->age = 33;
// p是实参的地址 *实参的地址 去间接的修改实参的值
*p = tmp;
}
//指针的引用 做函数参数
int getTeacher2(Teacher* &myp)
{
//给myp赋值 相当于给main函数中的pT1赋值
myp = (Teacher *)malloc(sizeof(Teacher));
if (myp == NULL)
{
return -1;
}
myp->age = 36;
}
void FreeTeacher(Teacher *pT1)
{
if (pT1 == NULL)
{
return ;
}
free(pT1);
}
void main1201()
{
Teacher *pT1 = NULL;
//1 c语言中的二级指针
getTeacher(&pT1);
cout<<"age:"<<pT1->age<<endl;
FreeTeacher(pT1);
//2 c++中的引用 (指针的引用)
//引用的本质 间接赋值后2个条件 让c++编译器帮我们程序员做了。
getTeacher2(pT1);
cout<<"age:"<<pT1->age<<endl;
FreeTeacher(pT1);
cout << "hello..." << endl;
system("pause");
}
3.5 常量的引用
#include <iostream>
using namespace std;
//常引用的知识架构
void main1301()
{
//普通引用
int a = 10;
int &b = a;
printf("b:%d \n", b);
//常引用
int x = 20;
const int &y = x; //常引用 是 让变量 引用只读属性 不能通过y去修改x了
//y = 21;
//常引用 初始化 分为2种情况
//1> 用变量 初始化 常引用
{
int x1 = 30;
const int &y1 = x1; //用x1变量去初始化 常引用
}
//2> 用字面量 初始化 常量引用
{
const int a = 40; //c++编译器把a放在符号表中
int &m = 41; //普通引用 引用一个字面量 请问字面量有没有内存地址
//引用 就是给内存取多个门牌号 (多个别名)
//printf("&40:%d \n", &40);
const int &m = 43; //c++编译器 会 分配内存空间
}
cout<<"hello..."<<endl;
system("pause");
return ;
}
//
struct Teacher
{
char name[64];
int age ;
};
//void printTeacher(const Teacher * const myt)
void printTeacher(const Teacher &myt)
{
//常引用 让 实参变量 拥有只读属性
//myt.age = 33;
printf("myt.age:%d \n", myt.age);
}
void main()
{
Teacher t1;
t1.age = 36;
printTeacher(t1);
cout<<"hello..."<<endl;
system("pause");
return ;
}