C++学习

一.C++版本对比C版本的hello world 输出

1.编写C++程序
c++程序必须要有一个main函数,也就是程序的入口函数,操作系统调用该函数来执行程序,main必须是小写
函数的组成部分:函数名称,返回值,形参列表,函数体

// c 版本的程序
#include<stdio.h>  // 标准输入输出
#include<stdlib.h>
int main()
{
	printf("hello world\n");
	system("pause");
	return 0;
}
//c++版本的程序
#include<iostream>//包含io库下的std::cout
int main()
{
	//标准命名空间 ostream = outstream
	std::cout<<"hello world!"<<std::endl;
	system("pause"); //暂停,便于调试
	return 0; //函数的返回值
}

2.输入和输出
C语言中使用prinf和scan进行输入输出,C++使用标准库中的IO流实现
Iostream中四个IO对象:输入cin输出cout错误cerr日志clog

//输入2个数求和,并打印出2个数的和
#include<iostream> 
//std 为命名空间 namesapce,防止相同文件名的命名冲突
int main()
{
	int a,b,sum;
	std::cout<<"输入2个数:"<<std::endl;
	std::cin>>a;//后台输入的数
	std::cin>>b;
//或者用std::cin>>a>>b;
	sum=a+b;
	std::cout<<a<<"+"<<b<<"="<<sum<<std::endl;
	system("pause");
	return 0;
}

3.流程控制

3.1 if else的判断
#include
int main()
{
//1.顺序执行
int pwd;
int count=0;
std::cout<<“请插入卡:”<<std::endl;
std::cout<<“请输入密码:”<<std::endl;
//2.做出选择
std::cin>>pwd;
if (pwd == 123)
{
std::cout<<“取钱1000”<<std::endl;
}else{
std::cout<<“密码错误,重新输入,你还有”<<3-count<<“次机会!”<<std::endl;
//循环三次2
while(++count<=3){
std::cin>>pwd;
if (pwd==123)
{
std::cout<<“取钱1000”<<std::endl;
break;
}else{
if(count<3)
{
std::cout<<“密码错误,重新输入,你还有”<<3-count<<“次机会!”<<std::endl;
}else{
std::cout<<“三次密码错误,您的卡已经被锁定!”<<std::endl;
}
}

		}//end while
}//else
system("pause");
return 0;

}//main()
3.2 三元运算
//三元运算:

#include<iostream>
int main()
{
	int a=1,b=2;
	int max=a>b?a:b;
	std::cout<<max<<std::endl;//2
	system("pause");
	return 0;
}

3.3 for循环

#include<iostream>
int main()
{
	int sum=0;
	for (int i=0;i<=10;i++){
		if (i!=2){
			sum=sum+i;
		}else{
			continue;
		}
	}//end for
	std::cout<<sum<<std::endl;//53
	system("pause");
	return 0;
}//end main

4.类对象介绍

4.1类的定义和声明
可以自己定义类型
自己定义get()set()方法

#include<iostream>
#include<string>
using namespace std;
//成员函数
class Person{
private:
	int _pid;
	string _name;
	int _age;
public:
	void setpid(int pid);
	int getpid();
	void setname(string name);
	string getname();
	void setage(int age);
	int getage();

};
void Person::setpid(int pid)
{
	_pid=pid;
}
int Person::getpid()
{
	return _pid;
}
void Person::setname(string name)
{
	_name=name;
}
string Person::getname()
{
	return _name;
}
void Person::setage(int age)
{
	_age=age;
}	
int Person::getage()
{
	return _age;
}

int main()
{
	Person per;
	per.setpid(1);
	per.setname("Tom");
	per.setage(20);

	int pid=per.getpid();
	string name=per.getname();
	int age=per.getage();
	per.getage();

	cout<<pid<<","<<name<<","<<age<<endl;
	system("pause");
	return 0;
}//end main

构造函数:在实例化对象的时候调用Person()
析构函数:清除对象的时候调用~Person()

#include<iostream>
#include<string>
using namespace std;
//成员函数
class Person{

private:
	int _pid;
	string _name;
	int _age;
public:
	//构造函数
	Person();
	//析构函数
	~Person();

	void setpid(int pid);
	int getpid();
	void setname(string name);
	string getname();
	void setage(int age);
	int getage();

};

Person::Person()
{
	cout<<"构造函数"<<endl;
}
Person::~Person()
{
	cout<<"析构函数"<<endl;
}

void Person::setpid(int pid)
{
	_pid=pid;
}
int Person::getpid()
{
	return _pid;
}
void Person::setname(string name)
{
	_name=name;
}
string Person::getname()
{
	return _name;
}
void Person::setage(int age)
{
	_age=age;
}	
int Person::getage()
{
	return _age;
}

int main()
{
	/*
	Person per; //构造函数
	
	per.setpid(1);
	per.setname("Tom");
	per.setage(20);

	int pid=per.getpid();
	string name=per.getname();
	int age=per.getage();
	per.getage();
	*/
	//指针的方式
	Person *per=new Person();//构造函数
	per->setpid(1);
	per->setname("Tom");
	per->setage(12);
	int pid=per->getpid();
	string name=per->getname();
	int age=per->getage();

	cout<<pid<<","<<name<<","<<age<<endl;//1,Tom,12

	delete per; //析构函数

	system("pause");
	return 0;
}//end main

关于头文件和源文件的使用:

per.h文件
#include<iostream>
#include<string>

using namespace std;
//定义写到头文件中
class Per
{
private:
	int _pid;
	string _name;
	int _age;
public:
	void setpid(int pid);
	int getpid();

	void setname(string name);
	string getname();

	void setage(int age);
	int getage();
};
Per.cpp文件
#include "per.h"
//调用头文件,实现在源文件
void Per::setpid(int pid)
{
	this->_pid=pid;
}
int Per::getpid()
{
	return _pid;
}
void Per::setname(string name)
{
	this->_name=name;
}
string Per::getname()
{
	return _name;
}
void Per::setage(int age)
{
	this->_age=age;
}
int Per::getage()
{
	return _age;
}
test.cpp文件
#include<iostream>
#include<string>//系统库用尖括号
#include "Per.h"//自己的使用双引号
using namespace std;
int main()
{
	Per per; //自定义;类型
	per.setpid(1);
	per.setname("Tom");
	per.setage(20);

	int pid=per.getpid();
	string name=per.getname();
	int age=per.getage();
	per.getage();
	
	cout<<pid<<","<<name<<","<<age<<endl;//1,Tom,12

	system("pause");
	return 0;
}//end main

二.数据类型

1.基本数据类型
包括:整数,浮点数,字符,布尔值,void
整型:int(1个字长) long(2个字长) short(半个字长)
浮点数:float double
字符:char 单引号括起来,可以与整型互换
bool:可以是true(非零数) false(零)
void表示无返回值,void*表示任意的对象类型

Test.cpp
#include<iostream>
#include<string>//系统库用尖括号
using namespace std;
int main()
{
	//布尔类型
	bool flag=true;
	cout<<flag<<endl;//1
	flag=false;
	cout<<flag<<endl;//0
	//字符类型
	char c='A';
	cout<<c<<endl;//A
	//字节大小
	cout<<sizeof(c)<<endl;//1
	
	//短整型
	short s=100;
	cout<<s<<endl;//100
	cout<<sizeof(s)<<endl;//2
	//长整型
	long l=2345;
	cout<<l<<endl;//2345
	cout<<sizeof(l)<<endl;//4

	//浮点型
	float f=3.14;
	cout<<f<<endl;//3.14
	cout<<sizeof(f)<<endl;//4
	//无符号类型
	unsigned int ui=123;
	cout<<ui<<endl;//123
	cout<<sizeof(ui)<<endl;//4表示4字节,32位

	system("pause");
	return 0;
}//end main

2.字面常量
为基本数据类型赋值的结果成为字面常量。例如int i=10;10被成为字面常量。
转义字符:\n\t\r\b 换行,table键 ,回车,退格
\’ \” 输出单引号双引号
3.变量
变量是内存里的一块存储区域,为该存储区域起一个名字name,age,通过这个名字可以操作这块存储区域,可以获得/修改它的值。
C++是一门静态类型的语言,编译时做类型检查,要求我们在定义变量的时候必须指定类型;类型决定了变量的内存大小和布局,取值范围,以及应用于该变量上的操作。
变量的初始化:是指定义变量的时候为变量赋值。分为:直接初始化(括号)或者拷贝初始化(等号赋值)。
函数体外部的被定义为0,函数体内的必须初始化。
类的初始化是调用构造函数。
变量的定义和声明:变量的定义用于为变量分配存储空间,还可以为变量赋值,变量只能定义一次。声明用于向程序说明变量的类型和名称,声明的时候不会分配存储空间。
例子说明:

#include<iostream>
#include<string>//系统库用尖括号
using namespace std;
int out; //函数体外部定义的
int main()
{
	//1.变量
	int age=23;
	//2.变量的命名
	string custume_name;
	string _name;
	int _age;
	//3.初始化
	int pid=1;  //拷贝初始化
	int pid1(2);  //直接初始化
	//4.初始化规则
	int in; //函数内部定义的,没有初始化,不用不报错,用了就报错。
	cout<<out<<endl;//默认是0
	//cout<<in<<endl; //函数体内部必须初始化,没赋值会报错

	//5.变量的定义和声明
	int x=100;    //定义:声明的同时初始化了
	extern int y; //声明

	system("pause");
	return 0;
}//end main

4.const的用法
(1)变量前面使用const关键字,表示该变量不可以被修改,即该变量是一个常量。

#include<iostream>
#include<string>//系统库用尖括号
using namespace std;
int main()
{
	//左值必须是可修改的,等号右边是右值
	int age=20;
	cout<<age<<endl;//20
	age=21;
	cout<<age<<endl;//21
	system("pause");
	return 0;
}//end main

(2)使用常量的好处:一是程序的可读性强,二是程序更容易被维护。
例如:

#include<iostream>
#include<string>//系统库用尖括号
using namespace std;
int main()
{
	//int arr[4*6];这样可读性差
	const int size=4*6;
	int arr[size];
	
	system("pause");
	return 0;
}//end main

(3)const默认为文件的局部变量,
全局作用域中的非const变量的作用域是全局的。
例如:

Per.cpp文件中
int a=100;//这样不报错
//const int a=100;这样使用会报错
Test.cpp文件 中
#include<iostream>
#include<string>//系统库用尖括号
using namespace std;
int main()
{
	extern int a;//没有extern会报错的
	cout<<a<<endl;//100
	
	system("pause");
	return 0;
}//end main

5.引用
(1)引用就是变量的别名,通常在函数的形参列表中
(2)定义引用的语法格式是在变量前面加“&”符号
例子:
//注意应用必须赋初始值
int a=100; //a表示张三
int &r=a; //r是张三的别名小张
cout<<r<<endl;//100
例子:

#include<iostream>
#include<string>//系统库用尖括号
using namespace std;
//copy 只是复制,没有实现交换
void swap(int a, int b)
{
	int temp;
	temp=a;
	a=b;
	b=temp;
	cout<<"a="<<a<<",b="<<b<<endl;
}
//reference  引用,用在函数的形参里面
void swap2(int &a,int &b)
{
	int temp;
	temp=a;
	a=b;
	b=temp;
	cout<<"a="<<a<<",b="<<b<<endl;
}	
int main()
{
	int a=1,b=2;
	swap(a,b); //a=2,b=1
	cout<<"a="<<a<<",b="<<b<<endl;//a=1,b=2
	swap2(a,b); //a=2,b=1
	cout<<"a="<<a<<",b="<<b<<endl;//a=2,b=1
	system("pause");
	return 0;
}//end main

6.类型定义
(1)typedef 用来定义类型的同义词,typedef int myint ;myint age;
(2)语法格式:typedef 数据类型 标识符
目的:
隐藏特定类型的实现,强调使用类型的目的;
简化复杂类型的定义,使其更容易被理解;
允许一种类型用于多个目的,同时使得每次使用该类型的目的明确;
例子:

#include<iostream>
#include<string>//系统库用尖括号
using namespace std;
//类型定义:可以包括内置类型or类or结构体
//结构体
typedef struct MyStruct{
	int x;
	int y;
}Point;
typedef class Person{
public:
	int pid;
}Teacher;
int main()
{
	//Teacher代表类
	Teacher t;
	t.pid=2;
	cout<<t.pid<<endl;//2
	//内置类型
	typedef int myint;
	myint age;
	myint pid;
	//Point代表结构体
	Point p;
	p.x=1;
	p.y=2;
	cout<<p.x<<p.y<<endl;//12

	system("pause");
	return 0;
}//end main

7.枚举
使用enum关键字定义有关联性的枚举类型
枚举成员是常量是,默认从0开始,也可以赋值;
例子:

#include<iostream>
#include<string>//系统库用尖括号
using namespace std;
enum direction{
	up,
	down,
	left1=100,
	right1
};//注意内部使用逗号,结束使用分号
int main()
{
	//枚举类型的第一个值默认从0开始
	cout<<up<<endl; //0
	cout<<down<<endl; //1
	//如果对某一个赋值,那么其后的依次一次递增,之前的仍是默认值
	cout<<right1<<endl; //101
	system("pause");
	return 0;
}//end main

例子2:

#include<iostream>
#include<string>//系统库用尖括号
using namespace std;
enum direction{
	up,
	down,
	left1=100,
	right1
};//注意内部使用逗号,结束使用分号,常量一般用大写
void change(direction d){
	switch (d){
	case up:
		cout<<"up"<<endl;
		break;
	case down:
		cout<<"down"<<endl;
		break;
	case left1:
		cout<<"left"<<endl;
		break;
	case right1:
		cout<<"right"<<endl;
		break;
	default:
		break;
	}// switch end
}

int main()
{
	change(up);//up
	system("pause");
	return 0;
}//end main

8.自定义类型
(1)类也是一种类型,使我们自己定义的一种类型;
(2)设计一个类的时候,先设计类的接口interface,再设计类的实现implementation;
(3**)接口是给客户来调用的,可以将类的接口定义在头文件(.h)中,类的实现定义在源文件(.cpp)中,并在源文件中包含头文件。**
例子:

per.h头文件
#include<iostream>//用到输入输出
#include<string>//用到字符串
using namespace std;
//接口写到头文件中
class Per
{
private:
	int _pid;

public:
	void setpid(int pid);
	int getpid();
};

class Pet
{
private:
	int _pid;
public:
	void setpid(int pid);
	int getpid();
};
Per.cpp源文件:
#include "per.h"
//实现接口 注意PerPet大写是指的per.h中的类名Per,Pet
void Per::setpid(int pid){
	//this是对当前对象的引用
	this->_pid=pid;
}
int Per::getpid(){
	return _pid;
}

void Pet::setpid(int pid){
	this->_pid=pid;
}
int Pet::getpid(){
	return _pid;
}
Tets.cpp源文件
#include<iostream>
#include<string>//系统库用尖括号
#include "per.h"
using namespace std;
struct MyStruct{
	int x;
	int y;
	//void func();//结构体内不可以定义函数
};
int main()
{
	Per p1;
	Pet p2;
	p1.setpid(20);
	p2.setpid(100);
	cout<<p1.getpid()<<endl; //20
	cout<<p2.getpid()<<endl; //100

	system("pause");
	return 0;
}//end main

三.sting and vector
1.命名空间
在文件系统中不能有2个同名的文件,这样会产生命名冲突。
命名空间解决命名冲突问题,关键字是namesapce
格式:
namespace名称{
变量,常量,函数等的定义
}
使用域访问符号“::”访问命名空间中的成员
例子:

#include<iostream>
#include<string>//系统库用尖括号
using namespace std;//系统定义好的命名空间
namespace MyNS1{
	//自定义命名空间中可以定义变量方法函数
	int a;
	int b;
	void f1();
	class Person{
	public:
		void f2();
	};
}
void MyNS1::Person::f2(){
	cout<<"f2"<<endl;
}
void MyNS1::f1(){
	cout<<MyNS1::a<<","<<MyNS1::b<<endl;
}
using namespace MyNS1;//使用这一行可以代替下面MyNS1::
int main()
{
	a=100;
	b=200;
	f1();
	Person per;//100,200
	per.f2();//f2
	/*
	MyNS1::a=100;
	MyNS1::b=200;
	MyNS1::f1(); // 100,200
	MyNS1::Person per;
	per.f2();//f2
	*/
	system("pause");
	return 0;
}//end main

2.string字符串
(1)C语言中使用字符数组;来表示字符串,
C++中提供string类来操作字符串;string支持长度可变的字符串,c++标准库负责管理与操作字符相关的内存,并提供各种有用的操作。
(3)使用string类需要包含string类头文件和std命名空间,
#include
using namespace std;
2.1字符串的定义和初始化:
void test1(){
string s;//默认构造函数,s1为空
string s2(s);//将s2初始化为s1的一个副本
string s3(“hello,world”);//将s3初始化为hello,world
string s4(2,‘a’);//将s4初始化为2个a字符的字符串
}
2.2字符串的读写
2.2.1例子:cin cout
#include
#include//系统库用尖括号
using namespace std;//系统定义好的命名空间
void test2(){
string s;
cout<<“please type string:”<<endl;
cin>>s;
cout<<s;
}
int main()
{
test2(); //输入hello world 输出hello空格之后的不能输出
system(“pause”);
return 0;
}//end main
2.2.2例子:循环读写
void testString(){
string s1;
while(cin>>s1){
cout<<s1<<endl;
if (s1==“bye”){
break;
}
}
}
2.2.3例子:getline
void getLine(){
string line;
cout<<“please type string:”<<endl;
while(getline(cin,line)){//读取cin的内容存到line
cout<<line<<endl;
if(line == “bye”){
break;
}
}//end while
}
2.3字符串的操作
判断是否为空,获取字符串长度。获取某个位置的字符
void test4(){
string s(“hello”);
bool result=s.empty();
cout<<result<<endl;//0
int size=s.size();
cout<<size<<endl;//5
char c=s[1];
cout<<c<<endl;//e
}
连接+ 比较2个字符串是否相等用==
3.vector向量
3.1介绍
向量是一种随机访问的数据类型,提供了对数组元素的快速,随机访问以及在序列尾部快速随机的插入和删除操作,是大小可变的向量。
3.2向量中常用方法
front:返回向量起始元素的引用
end:返回向量末尾元素的引用
begin:返回向量中第一个元素的迭代器
size:返回向量的大小
capacity:返回当前向量最多可以容纳的元素个数
clear:清除向量
insert(i,x):元素x插入到迭代器i所指的位置
empty:判断向量是否为空
erase(i):删除迭代器所指向的元素
erase(start,end):删除迭代器start和end范围内的向量元素
pop_back:删除向量中最后一个元素
push_back(x):在向量末尾添加x元素
例子:
#include
#include//系统库用尖括号
#include
using namespace std;//系统定义好的命名空间

int main()
{
vector v;
vector v1;
vector v2;
vector v3;

v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);

//iteration 迭代器遍历
vector<int>::const_iterator it = v.begin();
while(it!=v.end()){
	//*指的是指针,++优先级更高
	cout<<*it++<<endl;   //输出1-5
}
/*
//for循环遍历
int size=v.size();
for(int i=0;i<size;i++){
	cout<<v[i]<<endl;  //输出1-5
}*/
cout<<"遍历结束!"<<endl;
cout<<v.front()<<endl; //1 
cout<<v.back()<<endl;  //5 
it=v.begin();
v.erase(it+2);
cout<<v.size()<<endl; //4
system("pause");
return 0;

}//end main
四.数组和指针
1.数组
(1)数组可以保存相同的数据元素,长度是固定的;指针可以像迭代器一样遍历数组。
(2)数组是包含多个数据值(元素)的数据结构;每个数据值的类型相同;
(3)声明:说明类型的元素数量;int a[10]
(4)初始化:带有{}的常量列表;int a[]={1,2,3,4,5}
(5)访问:索引访问,下标是0开始;
for(int i=0;i<n;i++){}
例子:
#include
#include//系统库用尖括号
using namespace std;//系统定义好的命名空间

class Person(){
};
//1.数组保存基本数据类型
void test1(){

const int size=10;
int a[size];
for(int i=0;i<size;i++){
	a[i]=i+1;
}
cout<<a[0]<<endl;

}
//2.保存类 类型
void test2(){
const int size=2;
Per pers[size];
per p1;
Per p2;
pers[0]=p1;
pers[1]=p2;
}
int main()
{
test1();//1
system(“pause”);
return 0;
}//end main
2.指针
(1)指针也是一种变量,是指向另一种变量地址的变量。
保存的值是另一种变量的地址。
(2)作用:使用指针可以间接的操作指向的变量对象。
#include
#include//系统库用尖括号
using namespace std;//系统定义好的命名空间
void test1(){
int i=100;
int *ip = &i; // *解引用,&取地址
cout<<i<<endl; //对象本身 100
cout<<*ip<<endl; //对象本身 100
cout<<&i<<endl; //地址
cout<<ip<<endl; //地址
}
(3)声明:2种: int ip; int ip;
(4)指针的可能取值:
某个对象的地址;0值;指向某个对象后面的另外一个对象,用来操作数组。
#include
#include//系统库用尖括号
using namespace std;//系统定义好的命名空间
void test2(){
int a=100;
int *ad = &a;//另外一个变量的地址

int *p = 0;//不指向任何对象
int *q = NULL;//define NULL 0
const int x=0;
int *ip = x;// x=0 ok x=1 error
//int y=0;
//int *iq=y;//error 不是常量
int arr[] = {1,2,3};
int *ap = arr;//等同于 int *ap = arr[0]; 数组名称代表数组首地址
cout<<*ap<<endl;//1
ap++;
cout<<*ap<<endl;//2

}
(4)void 指针 可以保存任何类型对象的地址
#include
#include//系统库用尖括号
using namespace std;//系统定义好的命名空间
void test3(){
int i=100;
void
p = &i;
double d = 200;
void* q = &d;
}
//方法的返回值类型
void* test4(){
int i=100;
return &i;
}
//用于方法的形参
void test5(void* v){}
class Person(){};

int main()
{
Person *p=new Person();
test6§;//形参传递的类的对象

system("pause");
return 0;

}//end main
(5)指针的引用的区别:
引用总是指向某个对象,定义引用时没有初始化是错误的;初始化后不可以改变。
赋值行为的差异:给引用赋值修改的是引用所关联的对象的值,并不是引用与另外一个对象关联。
void test7(){
int i = 100;
int j = 200;
int &q = i; //引用必须初始化,初始化后不可改变,引用就是变量的别名
int *p; //指针可以不初始化
p = &i; //指针可以再赋值
p = &j;
}
void test8(){
int i = 100,j = 200;
int &pi = i, &pj = j;
cout<<“i=”<<i<<",j="<<j<<endl; //i=100,j=200
cout<<“pi=”<<pi<<",pj="<<pj<<endl; //pi=100,pj=200
cout<<"------------"<<endl;
pi = pj;//相当于i=j 指针的赋值指同一个对象,引用的赋值是它本身
cout<<“i=”<<i<<",j="<<j<<endl; //i=200,j=200
cout<<“pi=”<<pi<<",pj="<<pj<<endl; //pi=200,pj=200
}
(6)二级指针

void test8(){
int i=100;
int *p=&i;
int **q=&p;
cout<<p<<endl;//地址
cout<<*q<<endl;
}
(7)指向const对象的指针
void tes(){
const float *ppi;
const float pi=3.14;
ppi=π//pi是指向const对象的指针
cout<<*ppi<<endl; //3.14
}
//const指针,指针本身不能被修改
void test1(){
int i=100,j=200;
int *const pi=&i;
cout<<*pi<<endl;//100
}
//指向const对象的const指针
void test2(){
//两者都不能被修改
const double pi=3.14;
const double const pi_p = π
}
五.运算符和表达式
1.算数运算
算数运算符:加 减 乘 除 取余
运算符分类:
一元运算符:取地址&,解引用

二元运算符:加 减等
三元运算符:int max = i > j ? i : j
作用于内置类型,或者通过与运算符重载来操作类类型。
2.关系运算和逻辑运算
3.位运算
与 and &
或 or |
非 not ~
异或 xor ^ 相异为1
4.赋值运算
赋值运算的左值必须是非const的

5.自增自减运算
前置先计算后赋值;后置先复制后计算。
void test(){
int i=0,j=0;
cout<<++i<<endl; //1
cout<<j++<<endl; //0
}
//两次遍历1-5相同的效果,迭代器本身就是一种指针。
void test(){
const int length=5;
int arr[]={1,2,3,4,5};
for(int i=0;i<length;i++){
cout<<arr[i]<<endl;
}
cout<<"--------------"<<endl;
int *p = arr;
for(int i=0;i<length;i++){
cout<<*p++<<endl;
}
}
5.new 和delete
(1)使用new 和delete动态的创建和释放数组/单个对象。
class Person(){};
void test(){
int *i=new int();
string *s=new string(“hello,world”);
Person per;
Person *p=new Person();
//delete释放内存地址,但是仍然指向一个对象
delete i;
delete s;
delete p;
}
(2)new在自由存储区分配并创建一个对象,返回对象的地址(指针),我可以通过指针访问对象。
(3)动态创建对象的初始化,可以像初始化变量的方式来初始化,
class Person(){
public:
int pid;
int getpid();
};
void test(){
int *i=new int();
string *s=new string(“hello,world”);
Person per;
Person *p=new Person();
p->pid=100;
p->getpid();
//delete释放内存地址,但是仍然指向一个对象
delete i;
delete s;
delete p;
i=NULL; //重置指针,表示没有指向任何对象
}
(4)自由存储区被耗尽的时候,系统会抛出bad_alloc异常,也就是内存溢出,所以当我们使用new分配内存后,应该及时使用delete删除,释放内存。
使用delete之后,需要重置指针,否则指针还是指向原来的对象,这种指针称为悬垂指针。
(5)const对象的动态分配和释放与非const对象相同。
六.流程控制
1.简单语句
分号结尾,定义一个语句或者一个变量,空语句是只有一个分号;
复合语句:多个语句组成。block块。
//空语句的使用
void test(){
string s;
cout<<“输入一个字符串:”<<endl;
//第一种 更简洁
while(cin>>s&&s!=“bye”);
//第二种
while(cin>>s){
if(s==“bye”)break;
}
}
//空语句的使用
void test2(){
vector v;
v.push_back(1);
v.push_back(2);
v.push_back(3);

vector<int>::const_iterator it=v.begin();
while(it!=v.end())
	cout<<*it++<<endl;

}
2.声明语句
定义define和声明statement是有区别的:
int i;//表示定义一个变量
extern int j;//加了extern表示前面已经定义过这个变量,在这只是声明
class Person; //前导声明,只是用到类的名称,还没有定义类
class Person{}; //statement语句,语句必须分号结束
3.复合语句(block块语句)
函数体,方法体
4.条件语句
判断语句:
if else; switch;三元运算;
//判断三个数谁最大
void test(){
int a=100,b=1,c=2;
if(a>b){
if(a>c){
cout<<“a最大”<<endl;
}else{//c>a
cout<<“c最大”<<endl;
}
}else{//b>a
if(b>c){
cout<<“b最大”<<endl;
}else{//cbc
cout<<“c最大”<<endl;
}
}
}
5.循环语句
while;do while;for循环
例子while:
void test(){
int sum=0;
int i=1;
while(i<10){
sum=sum+i;
i++;
}
printf(“sum=%d\n”,sum);//sum=45
}
例子:for循环实现乘法表
void test(){
for(int i=1;i<=9;i++){
for(int j=1;j<=i;j++){
printf("%d*%d=%d “,j,i,j*i);
}
printf(”\n");
}
}
例子:
//0-10中偶数求和
void test(){
int sum=0;
for(int i=0;i<=10;i++){
if(i%2!=0){
continue;
}
sum=sum+i;
}
printf(“sum=%d”,sum);//sum=30
//cout<<sum<<endl;//30
}
七.函数
1.函数定义

2.参数传递

3.return语句

4.函数声明

5.局部对象

6.内联函数
6.1内联函数关键字:inline
例子:
inline void fun(){
cout<<“hello”<<endl;
}
6.2区别
普通函数:
main()函数《1》–>调用fun()函数《2》–>进入fun()函数头《3》–>执行fun()函数代码块《4》–>fun()函数结果《5》–>结束
内联函数:
编译时将函数体代码和实参代替函数调用语句,没有《2》《4》
适合简单函数,不适合复杂函数。
6.3类内定义:函数定义在类的内部。
类内定义的成员函数编译器会优先编译为内联函数。
6.4类外定义:成员函数的函数写在类的外面。
分类:同文件类外定义,分文件类外定义(一般选择这种)
自定义类型中讲到的例子就是分文件类外定义。
同文件类外定义例子:
#include
#include
using namespace std;
class Teacher{
public:
void setName(string _name);
string getName();
void setGender(string _gender);
string getGender();
void setAge(int _age);
int getAge();

void teach();

private:
string m_strName;
string m_strGender;
int m_iAge;
};
//类外定义:类名::方法名
void Teacher::setName(string _name){
m_strName=_name;
}
string Teacher::getName(){
return m_strName;
}
void Teacher::setGender(string _gender){
m_strGender=_gender;
}
string Teacher::getGender(){
return m_strGender;
}
void Teacher::setAge(int _age){
m_iAge=_age;
}
int Teacher::getAge(){
return m_iAge;
}
void Teacher::teach(){
cout<<“上课”<<endl;
}

int main(void){
Teacher t;
t.setName(“李四”);
t.setGender(“男”);
t.setAge(31);
cout<<t.getName()<<""<<t.getAge()<<endl;
t.teach();
system(“pause”);
return 0;
}

7.类成员函数

8.函数重载
方法名相同,形参列表不同。
构造函数的重载:
class Student(){
public:
//构造函数的重载
Student(){
m_strName=“Tom”;
}
Student(String name){
m_strName=name;//实例化的时候传值
}
private:
string m_strName;
};

八.其视频学习
OOP三大特性:继承封装多态
类是抽象的概念,对象是具体的事物,
类组成:数据成员和成员函数;
数据成员包括:普通数据成员+静态数据成员+对象成员+const+string
成员函数:属性封装函数+一般功能函数+特殊函数(构造函数+析构函数)
构造函数:拷贝构造函数+默认构造函数
类的使用:对象实例化
1.封装
隐概念:藏对象属性和实现细节,仅仅对外公开接口,
1.1访问限定符:
public private protected
1.2对象实例化
从栈实例化;从堆实例化
class TV{
public:
char name[20];
int type;
void changVol();
void power();
};
//从栈实例化对象
int main(void)
{
TV tv;//定义一个对象
TV tv[20];//定义一个对象数组,系统自动回收栈中内存
return 0;
}
//从堆实例化对象
int main(void){
TV *p=new TV();//指针指向一块内存,使用new 创建的,在堆中,手动释放
TV *q=new TV[20];//
delete p;
delete []q;
return 0;
}
1.3对象成员的访问
不同的实例化方法对应不同的访问方法
class TV{
public:
char name[20];
int type;
void changVol();
void power();
};
//从栈实例化对象
int main(void)
{
TV tv;//定义一个对象
tv.type=0;//对象访问成员的方式是点
tv.changeVol();
return 0;
}
//从堆实例化对象
int main(void){
TV *p=new TV();
if(p==NULL){
//内存地址p是NULL,说明申请失败
Return 0;
}
p->type=0;
p->changeVol();
delete p;//释放内存
p=NULL;
return 0;
}
1.4数据的封装
get set方法
例子:
#include
#include
#include<stdlib.h>
using namespace std;
class Student{
public:
//这就是类内定义,按照inline执行
void setId(int id){
m_iId=id;
}
int getId(){
return m_iId;
}
void setName(string name){
m_strName=name;
}
string getName(){
return m_strName;
}
private:
//这里面定义的是数据成员
int m_iId;
string m_strName;

};
int main(void){
Student std;
std.setId(001);
std.setName(“Tom”);
cout<<std.getId()<<endl;
cout<<std.getName()<<endl;

system("pause");
return 0;

}

2.对象结构
2.1内存分区:
栈区:int x=0; int *p=NULL;//内存由系统控制
堆区:int *p=new int[20];//new出来的需要自己delete
全局区:存储全局变量及静态变量
常量区:string str=“hello”;
代码区:存储逻辑代码的二进制
2.2对象初始化:
分类:有且仅有一次的初始化;根据条件初始化;
2.3构造函数:
在对象实例化的时候被自动调用;仅被调用一次

构造函数与类名同名,没有返回值,可以有多个重载形式,
即使有多个构造函数,但是实例化时仅有一个;
当用户没有定义构造函数的时候,编译器自动生成一个构造函数;

默认构造函数:实例化对象时不需要传递参数;
但是一个类可以没有默认构造函数。
2.4 构造函数初始化列表
例子:
class Student{
public:
//初始化列表这样
Student():m_strName(“Tim”),m_iAge(10){}
private:
string m_strName;
int m_iAge;
};
初始化列表先于构造函数执行;
初始化列表只能用于构造函数;
初始化列表可以同时初始化多个数据成员;
说明初始化空列表的必要性例子:
class Circle{
public:
//Circle(){m_dpi=3.14}//这样会报错,const是常量
Circle():m_dpi(3.14){}//这样可以编译通过
private:
const double m_dpi;
};

2.5 拷贝构造函数
构造函数:
无参构造函数:默认构造函数;
有参构造函数:参数带默认值,参数无默认值;
系统自动生成的函数:
普通构造函数和拷贝构造函数
定义格式:类名(const 类名& 变量名)
拷贝构造函数不可以重载,因为参数是确定的;
当没有自定义的拷贝构造函数时,系统自动生成一个拷贝构造函数;

#include
#include
using namespace std;
class Student{
public:
Student(){
cout<<“Student”<<endl;
}
};
int main(void){
Student stu1;//只打印一行 Student
Student stu2=stu1;//这一行没执行?
Student stu3(stu1);

system("pause");
return 0;

}
拷贝构造函数
定义格式:类名(const 类名& 变量名)
#include
#include
using namespace std;
class Student{
public:
Student(){
m_strName=“Tim”;
cout<<“one”<<endl;
}
Student(const Student& stu){
cout<<“two”<<endl;
}
private:
string m_strName;

};
int main(void){
Student stu1;//one
Student stu2=stu1;//two 说明调用的是拷贝构造函数
Student stu3(stu1);//two
system(“pause”);
return 0;
}

2.6 析构函数
任务:完成系统资源的归还。
定义格式:~类名()
如果没有自定义的析构函数,则系统自动生成;
析构函数在对象销毁时自动调用;
没有返回值,没有参数也不能重载。
例子说明:
第一个Teacher.h文件中:
#include
#include
using namespace std;

class Teacher{
public:
Teacher(string name=“Jim”,int age=12);
Teacher(const Teacher& tae);
~Teacher();//定义析构函数

void setName(string name);
string getName();
void setAge(int age);
int getAge();

private:
string m_strName;
int m_iAge;
};
第二个Teacher.cpp文件中:
#include “Teacher.h”
using namespace std;
Teacher::Teacher(string name,int age):m_strName(name),m_iAge(age)
{
//普通构造函数
cout<<“Teacher(string name,int age)”<<endl;
}
Teacher::Teacher(const Teacher& tea)
{
cout<<“拷贝构造函数”<<endl;
}

Teacher::~Teacher(){
cout<<“析构函数”<<endl;
}

void Teacher::setName(string name){
m_strName=name;
}
string Teacher::getName(){
return m_strName;
}
void Teacher::setAge(int age){
m_iAge=age;
}
int Teacher::getAge(){
return m_iAge;
}
第三个one.cpp文件中:
#include
#include<stdlib.h>
#include
#include “Teacher.h”
using namespace std;
//定义格式:类名(const 类名& 变量名)
void test(Teacher t1){

}
int main(void){
/*
Teacher t;//Teacher(string name,int age)
test(t);//拷贝构造函数
/
/
使用堆初始化
Teacher *p=new Teacher();//Teacher(string name,int age)
delete p;//析构函数
*/
Teacher t;//Teacher(string name,int age)
Teacher t2(t);//拷贝构造函数
system(“pause”);
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值