目录
面向对象:
结构体:管理多个不同类型数据的数据结构
C++支持面向对象:
面向过程: 函数
面向对象: 数据
事 物 : 对象
抽象
结构,类: 事物共性和特性的集合 类型
属性-数据 成员变量
功能-流程 成员函数
结构体,对象: 实例
具体存在,占内存
0x00.区别C++中的struct 和class
排除public和private的影响,struct和class没有任何区别。因为C++的struct也可以有成员函数。
一般只有属性 用 struct
有属性有功能 用 class
- struct的成员默认为公有。
- class的成员默认为私有。
private: 声明成员变量和成员函数为私有。
私有成员变量和成员函数只有 类的对象的成员函数可以访问,不能通过对象名去访问,但是可以用指针从底层绕过,对私有成员变量进行读写操作。
public: 声明成员变量和成员函数为公有。
可以通过对象名访问,也可以通过成员函数去访问。
封装:通过private来保护成员变量和成员函数。
万物皆对象:
抽象是面向对象的基础。
面向对象三大特性:
封装 继承 多态
0x01 .名字空间:
作用:区分标识符,保证标识符的使用的唯一性
- 名字空间的定义
-
namespace 名字空间名{ 声明标识符 };
-
- 名字空间的使用
- 方式1: 名字空间名::标识符
- 方式2:using namespace 名字空间名;
- 使用了之后就全部都是这个名字空间,不能取消
- 使用了之后暴露名字空间里所有的名字
- 方式3:
- using 名字空间名::标识符;
- 只暴露名字空间中单个名字。
0x02 C++开发展望:
项目经理 架构师 工程师 总工
只写主函数 和 声明类 设计师 工程师
程序员 开发
只定义类中成员函数 施工员
游戏开发:
主程
开发
返回类型名 函数名(参数列表){
return 返回值;
}
0x03构造函数
构造函数:
- 类构造对象的时候自动调用的函数。
- 如果不自定义构造函数,编译器会自动生成构造函数。
构造函数特性:
1.函数名与类名相同
2.没有返回类型名
3.构造函数一定会被调用并且只会被调用一次(在对象生成的时候)
构造函数能不能被重载:
能。
构造函数被调用多少次:
一个对象只调用一次构造函数。
一个类可以有N个对象,每个对象可以调用不同的构造函数。
// 类和对象.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <string>
using namespace std;
Class Beer{
private:
//属性
string color;//28
int dushu;
public:
//功能
void makeHappy();
void dajia();
void init(string c, int d);
};
//update2019.4.24:注意这里只是定义了一个类型,内存中并没给这个类型分配内存,定义类型的作用只是告诉编译器,有这样一种类型。只有当用这种类型去声明一个变量的时候,才会给该变量分配内存。
//update2019.4.24:类名+作用域标识符的作用:区分不同类中的同名函数
void Beer::init(string c, int d){
color = c;
dushu = d;
}
void Beer::makeHappy(){
printf("何以解忧,唯有%s颜色的%d度的啤酒!\n", color.c_str(), dushu);
}
void Beer::dajia(){
printf("我一口%s颜色的%d度的啤酒喷死你啊!\n", color.c_str(), dushu);
}
int _tmain(int argc, _TCHAR* argv[])
{
Beer hapi;
//update2019.4.24:在函数内部声明变量,在内存中的栈区为变量hapi分配内存。分配多大内存由类型Beer决定。即可以大致认为是Beer中成员变量的所应占内存空间大小的简单加和(实际上,编译器为了寻址方便,有更为复杂的一套分配内存的规则,一个成员变量得到的空间可能大于它原本应占据的空间,但绝对不会小于原本应占据的空间),因为类中的成员函数即便是实例化之后也只是函数声明,所以不占内存。
hapi.init("黑色", 13);
/*
printf("对象大小为:%d\n", sizeof hapi);
hapi.init("黑色", 13);
// hapi.color = "黄色";
// hapi.dushu = 12;
//update2019.4.24:封装就是绝对的安全吗?请看下面的骚操作,通过指针从底层绕过封装。
//1.获取对象的首地址,并强制类型转换。
// string* pStr = (string*)&hapi;//取结构体hapi的地址其实是取结构体hapi所分配内存空间的首地址,也就是string color 的首地址。
//update2019.2.24:指针类型的作用就在于,当指针变量加1或者减1寻址的时候,告诉编译器这个“1”的大小。例如:
string*类型的指针变量pStr++实际上会被编译器解释为:pStr=pStr+1*sizeof(String)
而Beer*类型的指针变量pStr++会被编译器解释为:pStr=pStr+1*sizeof(Beer),所以,虽然这里结构体hapi的首地址就是它的第一个成员变量string color的首地址,但是必须强制类型转换,否则通过首地址加减一个数去寻址就会出现严重的错误!
//2.通过首地址寻址,来访问被封装的变量。
printf("%s\n", pStr->c_str());//也就是说虽然封装了,但是还是可以通过寻址的方式来访问结构体中的元素。
//update2019.4.24:由于C语言中没有string类型的对象,所以通过C的格式化输出来输出string类型对象的时候,必须调用string类型对象的c_str函数,将string类型的对象转化成为c能理解的字符数组。
pStr++; //寻址到被封装的第二个成员变量
int* pInt=(int*)pStr;
printf("%d",*pInt);//输出第二个成员变量。
(*pInt)=996;//对封装变量进行写操作
//update2019.4.24:总结:封装在熟练操作指针并且一心想读写封装变量的hacker面前就是小儿科,毫无安全性可言。所以,只能说封装指示相对的安全,(主要是防止队友无意中坑自己)并非绝对的安全。
*/
while (1);
return 0;
}
// namespace.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
using namespace std;
//using std::cin;
namespace name1{
int age = 10;
double score = 1.1;
char name[20] = "zhangfei";
}
namespace name2{
int age = 20;
}
//int age = 666;
int _tmain(int argc, _TCHAR* argv[])
{
// printf("age:%d\n", age);
// printf("age:%d\n", name1::age);
// printf("age:%d\n", name2::age);
using namespace name1;
printf("age:%d\n", age);
int n;
cin >> n;
cout << n << endl;
while (1);
return 0;
}