C++(吕鑫)

 Day 1

2、new-delete语法简介:

a)C语言中需要使用malloc与free申请与释放堆空间:

b)C++把堆空间申请与释放做成关键字,底层也是malloc和free。

c)用起来绝对舒服,成为关键字不用包含头文件。

d)就如同栈一样的模式,比如:栈内申请一个数组:int a[20];

堆内:int* p = new int[20];//堆数组,中括号内可以代入变量,如int n=20;int* p=new int[n];

new和delete代替malloc-free特别方便
	int n = 20;
	int* p = (int*)malloc(sizeof(int)*n);//给我来20个int
	//int* p = new int[n];


1、在堆空间上分配和释放单个变量
TYPE * p = new TYPE;
delete p;

类似于栈内的:
int n = 888;
int *p = new int(888);
int *p = new int{888};
SNode* p = new SNode{d};//C++11可以在这把d和NULL带入,

	//p->data = d;
	//p->pNext = NULL;

2、在堆空间上分配分配和释放数组(多个变量)
TYPE * p = new TYPE[N]; //N可以是变量
delete []p;
类似于栈内的:
double a[N];//栈内申请数组只能是常量
double *p = new double[N];
分配并初始化:double* p=new double [n]{88,98,34,33};

注意:申请时带中括号[],释放时也要delete []p;
3、在堆空间上分配和释放指针数组;
auto p = new const char* [] { "abc", "efg", "test", nullptr };
delete []p;




单个堆变量专题:
int main()
{//98版本的C++
	int* p = new int;
	*p = 888;

	delete p;

	return 0;
}

	int* p = new int(888);//C++98
	int* p = new int{ 888 };//C++11
int main()
{//2011版本的C++
	int* p = new int{ 888 };

	delete p;

	return 0;
}

//c++在堆区创建二维数组
98版C++支持堆二维数组(不支持初始化):	double (*p)[12] = new double[3][12];
11版C++支持初始化:double (*p)[12] = new double[3][12]{{12,4,6},{22,33,5,55}};


int main()
{//2011版本的C++
	SData data = { 1002,"Alice",8983.55f };
	SData* p = new SData{ 1002,"Alice",8983.55f };
	delete p;
	return 0;
}

3、cin和cout语法简介:

a)C++系统的头文件不加.h,故意可以防止与自己的头文件冲突。
b)cin和cout最大的特点就是类型自动识别,比printf的%d,%f要好用多了
c)cin的时候也不用取地址,为什么呢?实际上内部语法是引用型变量(自动转帮你取地址)。
d)cout <<"\n"一般会使用cout << endl;代替//end of line

cout 不足之处是占位不如printf("%-8.2f"..)好用。

4、namespace命名空间:

a)这个语法是为了解决变量和函数名字冲突;
b)比如每个程序员用自己的姓名作为分类名称,namespace类似加了一个外壳。
c)using namespace xxx,就代表把壳去掉。

#include <iostream>
using namespace std;
namespace LVXIN
{
	double g1 = 0.8;
	int add(int a, int b)
	{
		return a + b;
	}
}
double g1;
//名字 空间
int main()
{
	LVXIN::g1 = 888.88;
	LVXIN::add(6, 8);//虽然这个语法很烂,也或许是C++类的起源语法。
	g1 = 999;
	cout << "LVXIN::g1的地址:" << &LVXIN::g1 << endl;
	cout << "g1的地址:" << &g1 << endl;
	return 0;


//如果加上using namespace LVXIN,
    LVXIN::g1 = 888.88;g1 = 999;这两个语句会发生冲突
    修正:LVXIN::g1 = 888.88;::g1 = 999;(::g1前面两个冒号代表无壳,表示不属于任何命名空间)
}


Day 2

引用型变量:

a)C++掩盖真相的语法之一,其内部真实原理就是指针变量。
b)引用做参数时主调函数好用,替你取地址,被调函数也好用,不用*符号;
c)类似于指针常量,指针常量的意思就是指向某个地址,在生命期内再不能改了;
d)另外指针常量的特点是必须初始化,引用型变量必须在定义的同时挂在某个变量上。

#include <iostream>

int main()
{
	int m = 888,n=-1;
	int* const p;//错误,必须初始化
	int* const p = &m;
	p = &n;//错误,初始化后就不能再指向别的变量

	int& k;//错误,必须初始化
	int& k = n;
	k = 0;//等价于*p = 0;
	k = m;//这个语句是赋值不是挂载语法
	return 0;
}

Day3

3.2 vector系统类库分析

2、C++封装类的高明:有两项高明
a)通过封装类,程序员可以定义任意多的动态数组对象(链表对象等)
(你想想C语言能实现吗?)
b)模板技术也叫泛型技术,程序员可以定义任意多种类型的数据来使用算法类。
比如:
vector<double> v1;
vector<SInfo> v2;

3、this指针的原理:
a)没有真正的成员函数,类内没有函数,C++是隐藏了真相的语言。
b)真实的情况是每个成员函数内都有一个this,指针变量指向来源对象。
c)在成员函数运算过程中,可以调用this指针指向的对象内的数据。
 

#include <iostream>
using namespace std;
const float PI = 3.14159f;
struct Circle
{
	double   radius;
	double Circumference()  //圆周长 struct Circle* const this,this指针的类型是struct Circle* const
	{
		this = NULL;//错误,因为有const,所有this指向的内容不能改变
		this++;//错误,因为有const,所有this指向的内容不能改变
		return 2 * PI * this ->radius;
	}
	double Area()  //圆面积
	{
		return PI * this->radius * this ->radius;
	}

};
int main()
{
	float radius;
	cout << "sizeof(struct Circle)=" << sizeof(struct Circle) << endl;
	cout << "请输入游泳池的半径: ";
	cin >> radius;
	// 声明 Circle 对象
	Circle Pool = { radius };
	Circle PoolRim = { radius + 3 };
	//计算栅栏长度
	cout << "栅栏长度是:" << PoolRim.Circumference() << endl;
	cout << "甬道的面积是:" << PoolRim.Area() - Pool.Area() << endl;
}
#include <iostream>
#include <vector>
using namespace std;
int add(int a, int b)
{
    return a + b;
}
add(88, 99) = 99;//错误,此处不能做左值

int g1;
int* Test()
{
    return &g1;
}
Test() = NULL;//错误,此处不可做左值
*Test() = 666;//正确,降级后可做左值

int ga[] = { 8,9,1,1,2,3,4,5,6 };
int& at(int n)
{
    return ga[n];
}
at(6) = 666;//正确,此处可做左值

vector<int> myvector(10, 8);   
size_t nSize = myvector.size();
for (unsigned i = 0; i < nSize; i++)
    myvector.at(i) = i;//正确,at()函数可做左值

3.3 vector 类成员函数演示

1.

  •  int n = (int) myvector.size();//c语言形式,myvector.size()返回值是long long类型,需要强制转换
  •     int m = int(myvector.size());//c++形式
  •     int m1(myvector.size());//c++形式

2.

//输出结果:10 20 0 100 0
int main()
{
	std::vector<int> myvector(5);
	int* p = myvector.data();

	*p = 10;
	++p;
	*p = 20;
	p[2] = 100;

	std::cout << "myvector contains:";
	for (unsigned i = 0; i < myvector.size(); ++i)
		std::cout << ' ' << myvector.at(i);
	std::cout << '\n';
	return 0;
}	

3.4 试图用vector开发项目

1.头文件main.h中一般不放using namespace std;

2.声明放在头文件中,声明可以重复,定义不能重复

4.2 视频末尾的

 自行csdn中学习typedef函数指针

Day4

4.4 class关键字与权限管理

重载函数:overload-function
a)相同的区域内,同名函数,参数不同(个数和种类)。
b)例如:两个类内有相同名字的函数不是重载。
c)同在全局区或者同一类内相同名字不同参数就是重载。
d)它是今后泛型语法起源,C++模板技术的内部原理就是重载的继续升级。

struct默认所有成员都是public,class默认所有成员都是私有的。

Day 5

5.1 pass

5.2 5.3复杂类对象之间功能相互调用,很难,已pass,需要多回顾

5.4 static

请列出static关键字有哪些作用?
C语言有两种:修饰全局变量(函数)和修饰局部变量。
C++还有两种:修饰成员变量和成员函数。


面试题:在C语言中,static关键字的作用有哪些?
a)在一个函数前加上static关键字修饰之后,这个函数将禁止被跨文件访问,只限于在当前源文件中使用;
b)在一个全局变量的定义前加上 static修饰之后,这个全局变量也将被禁止跨文件访问,只限于在当前源文件中使用;
c)如果一个全局变量或函数不加static修饰时,在整个软件工程中只能有一份同名的全局变量或函数,否则在编译时将出现连接错误;
d)如果一个全局变量或函数加了static修饰之后,每一个源文件中都可以有一份同名的全局变量或函数,而编译时不会出现(同名冲突的)连接错误;


e)如果在一个函数内的局部变量前加上static修饰之后,这个变量已经不是纯粹的局部变量了。编译之后它与全局变量处于同一空间内,这个函数内的静态变量的生命期与全局变量相同,变量在程序进入main函数之前已经初始化完毕。


在C++语言中,static还有另外两个功能,就是修饰成员变量与成员函数。


1、静态成员函数:
a)普通成员函数中都有一个隐含的形参(this)
b)静态成员函数不含有this参数,静态成员函数是C格式函数(纯函数)
c)普通成员函数在调用时必须要用对象调用。
d)静态成员函数可以使用对象调用,也可以直接用类名调用。
e)静态成员函数跟对象无关,只是名义上划分给某个类(实质全局函数)。
对于静态成员函数,可以认为类名只是域名namespace
box::f1();

e)静态成员函数中不可以调用其他普通成员,只能调用本类或者其他类的静态成员。
f)普通成员函数可以调用静态成员(变量和函数)。

2、静态成员变量:
a)普通的成员变量,每定义一个类对象该成员变量都跟对象一起申请新的空间。
b)即静态数据成员在内存中只有一份空间,生存期为整个程序运行期。
c)在类内只是一个声明(无空间),静态数据成员必须在类体外进行定义和初始化。
d)静态成员变量在进入main函数之前已经执行了定义有了空间,而普通成员只有在对象定义时才有空间。

//test.cpp

#include<iostream>
using namespace std;
void Test()
{
	cout << "测试" << endl;
}

//main.cpp

void Test();//声明
int main()
{
	Test();//跨文件调用Test(),需要声明
}
//test.cpp

#include<iostream>
using namespace std;
static void Test()//static声明后,阻断隔壁的调用
{
	cout << "测试" << endl;
}

//main.cpp

void Test();
int main()
{
	Test();//此时无法调用
}
//test.cpp

#include<iostream>
using namespace std;
double g_d=888.88

//main.cpp

extern double g_d;//声明
int main()
{
	g_d=999.99;//此时test.cpp中的g_d也变为999.99
}
//test.cpp

#include<iostream>
using namespace std;
static double g_d=888.88//static修饰后,隔壁无法调用

//main.cpp

extern double g_d;//声明
int main()
{
	g_d=999.99;//错误,无法调用
}

应用:1.普通回调函数一般不可以放在类内作为成员函数,一般是定义为全局函数,加上static后的回调函数可以放在类内

2.跟对象无关的函数可以用static,名义上划分给某个类

Day 6

6.1 pass

6.2构造函数

构造函数(constructor):
a)构造函数是类的一种特殊成员函数,一般情况下,构造函数是专门用来初始化对成员变量的
,所以最好不要在构造函数中进行与对象的初始化无关的操作。
b)构造函数的函数名一定与类型完全相同,而且没有返回值(不是说返回值是void或者int,而是说不允许指定返回值)。
c)构造函数的返回值如果指定了任何类型都是错误,构造函数的功能是代替C语言对结构体对象初始化的大括号。
d)C语言对结构体成员初始化方式是使用大括号,如果该类(结构体)有构造函数就禁止使用大括号初始化成员数据。

 

#include <iostream>
using namespace std;
class Student
{
public:
	const char* name;
	int age;
	float score;
};
int main()
{
	Student s1 = { "小明",22,99 };//当成员变量是public时,可以用类似这样c语言风格的初始化
}
#include <iostream>
using namespace std;
class Student
{
public:
	void set(const char* p, int a, float s)
	{
		name = p;
		age = a;
		score = s;
	}
private:
	const char* name;
	int age;
	float score;
};
int main()
{
	Student s1 ;//当成员变量是private时,需要先定义对象,再调用共有接口去初始化
	s1.set("小明", 22, 99);
}
#include <iostream>
using namespace std;
class Student
{
public:
	Student(const char* p, int a, float s)
	{
		name = p;
		age = a;
		score = s;
	}
private:
	const char* name;
	int age;
	float score;
};
int main()
{
    //C++98
	Student s1("小明", 22, 99);//优化上一个方案,将定义对象和初始化结合为一步,用构造函数
	//C++11
    Student s1={"小明", 22, 99};
    //C++11
    Student s1{"小明", 22, 99};
}

2、构造函数调用,
a)是在定义对象时指定参数或者不指定参数,都自动调用构造函数。手工使用对象调用构造函数出错。
b)构造函数分为无参数,有参数和拷贝构造函数。定义了哪形式的构造函数,就意味着类有哪种对象定义方式。
c)使用=符号来调用构造函数,调用单参数的构造函数而且单参数类型和=符号右边的类型相同。
d)一般情况下=符号右边的类型没有适合单参数构造函数就不能使用=符号构造
e)只有一种类型不需要适合=符号右边构造函数。系统内部有缺省的拷贝构造函数,内部实现的是整体赋值。(还有一个缺省是operator=)

6.3 pass

Day 7

7.1 初始化列表起源

#include <iostream>
using namespace std;
class Student
{
public:
	Student(const char* p, int a, float s)
	{
		name = p;//这里的语句是赋值语句,不是初始化语句
		age = a;
		score = s;
		a = NULL;//这里的语句是赋值语句,不是初始化语句
	}
private:
	const char* name;
	int age;
	float score;
	double* const a=NULL;//C++ 98不支持在这个地方初始化,而构造函数里是赋值语句不是初始化
						//语句,然而指针常量要求必须初始化,该怎么办?
};

7.2 初始化列表

#include <iostream>
using namespace std;
class Student
{
public:
	Student(const char* p, int a, float s) :a(NULL)//用初始化列表可以解决这个问题
	{
		name = p;//这里的语句是赋值语句,不是初始化语句
		age = a;
		score = s;
	}
private:
	const char* name;
	int age;
	float score;
	double* const a;
};

1、必须初始化的变量类型:
a)常变量:const int n;//必须初始化
b)引用:int & m;//必须初始化
c)指针常量:int * const p;//必须初始化
d)构造函数有参数,没有无参数构造函数(default constructor)

2、以上三种必须初始化的变量放在类成员中怎么办?
a)使用C++11直接用等号或者大括号 const int m_age{99};
b)C++98要使用初始化列表   :
Student(const char* p, int a, float &f):m_age(a),m_fTest(f)
引用传值,可以等同于目标对象,直接a.
第四种:
成员对象必须传参的时候也要使用初始化列表完成。

3、初始化列表格式:
a)只能用于构造函数
b)冒号后面是成员变量,小括号内是右值

7.4 构造vector类

1.默认参数

#include <stdio.h>
//int add(int a, int b)
//{
//	return a + b;
//}
//int add(int a, int b, int c)
//{
//	return a + b + c;
//}
//把以上所有的函数合并成一个函数
int add(int a, int b, int c=0,int d=0)
{//注意点:就是必须从后往前默认 int add(int a=0, int b, int c=0,int d=0),这样是错误的
	return a + b + c + d;
}
int main()
{
	int n = add(88, 99);//至少2个实参
	int m = add(88, 66, 77);
	int d = add(88, 66, 77,-33);
	//int x = add(8);//一个参数编译错误
	return 0;
}
}

2.清零函数

#include <iostream>
using namespace std;
int main()
{
	int a = int();
	cout << a << endl;//a=0
}

Day 8

8.1 内联函数

1、inline函数简介:
a)有一道面试题,在C语言中如何实现inline函数?
b)类似于C语言的宏函数,不进出栈,速度快。
c)inline这个英文可以翻译成,在当前行内执行。
d)C++类成员函数中,如果是单行函数尽量把函数体放在头文件中。
编译器会自动加inline进行编译,加快程序运行速度。
e)内联函数不能太复杂,比如好几个循环,编译器内联不成功。

特点:就是速度比真正的函数速度块。

#include <iostream>
using namespace std;
inline int add(int a, int b)
{
	return a + b;
}
//相当于c语言的宏函数
//#define add(a,b)(a+b);
int main()
{
	int m = add(88, 99);

}

8.2 string类

构造函数的调用方法:
a)string s1 = s0;//98C++,只限于单参数构造
b)string s1(s,5);//98C++ 
c)string s1{s,5};//C++11推荐
d)string s1={s,5};//C++11

8.3 、C++致命性错误分析:以string为例

string s = "abc";
a)不能写入文件
fwrite(&s,szieof(s),1,pf);
b)发送给网络另一台电脑。
send和sendto
c)不可以memcpy和memset等操作

8.4析构函数

析构函数:
a)析构函数是对象销毁时自动调用函数;
b)栈对象析构函数发生的时间是离开函数时,被系统自动调用;
c)全局对象析构函数发生在什么时候?
全对象的构造发生在main函数进入之前,析构发生在main结束之后.

5、析构函数的作用:
a)不是所有类都必须要做析构函数?
比如:Admin类或者Worker类中没有指针变量,这种普通的类就不需要析构函数。
b)像vector,string这种类内部有指针,并且构造后会调用new。
这种类内部是需要析构函数清理运行过程new过的空间。
c)析构函数  释放的空间往往是指针指向的底层数据,结构体或者类内的空间是自动释放的。
 

Day 9

9.1过

9.2 9.3还需回顾

9.4 

 对于c

at()函数这里如果用中括号会错误

 此时可以重载运算符中括号

 此时就可以用中括号了

Day 10

10.1 10.2 pass

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值