大橙子网站建设,新征程启航
为企业提供网站建设、域名注册、服务器等服务
根据之前学习的进行总结,温故而知新,理解有误请大佬们评论区指正,感谢~
基本概念理解在整个代码编译过程中,除了语言上的标准外,对编译的概念理解通透也是必需的:
关于.h .hpp .cpp的理解#ifndef TEST_H_
#define TEST_H_
///代码
#endif
封装成dll和lib区别首先,dll和lib都是链接库,dll是动态链接库,lib是静态链接库。静态库是指在链接的过程中,将该库中的代码完全复制到可执行文件中;动态库是指可以被不同进程调用但不属于可执行文件的函数,可由多个程序同时使用。总之,lib是编译时用到的,dll是运行时用到的。
stdafx.h和stdafx.cppStdAfx.h, StdAfx.cpp这些文件用于生成名为.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
全局变量global和静态变量static区别全局变量和静态变量在内存中存放在同一位置,即静态区/全局区。
从作用域来看:
静态变量的生命周期为整个源程序,其作用域仍与普通变量相同
静态全局变量也具有全局作用域,他与全局变量的区别在于如果程序包含多个文件的话,他作用于定义它的文件里,不能作用到其他文件里,即被static关键字修饰过的变量具有文件作用域。这样即使两个不同的源文件都定义了相同的静态全局变量,他们也是不同的变量
从生命周期看:
都在程序运行时期全程有效
全局变量:用extern声明,也称之为外部变量,是在方法外部定义的变量。它不属于哪个方法,而是属于整个源程序。作用域是整个源程序。如果全局变量和局部变量重名,则在局部变量作用域内,全局变量被屏蔽,不起作用。编程时候尽量不使用全局变量。
静态变量:用static声明,从面向对象的角度触发,当需要一个数据对象为整类而非某个对象服务,同时有力求不破坏类的封装性,既要求此成员隐藏在类的内部,有要求对外不可见的时候,就可以使用static。
argc 是 argument count的缩写,表示传入main函数的参数个数;
argv 是 argument vector的缩写,表示传入main函数的参数序列或指针,并且第一个参数argv[0]一定是程序的名称,并且包含了程序所在的完整路径;
通常我们知道有变量和常量的定义,例如int a=10; 那么a是个变量,值可以变的量;10是个常量,值不能变的量;那么在c++中例如用const int a=10,理论上a是个变量,但由于const限定符,导致其是个常量,因此将其称之为符号常量;符号常量的定义通常有两种方式实现:#define和const,区别是define只是做个文本替换
枚举类型enumenum称为枚举数据类型,就是可以一个个列举出来的东西,比如星期几或者性别,可以清楚知道里面有什么内容的数据,一般使用形式是 enum 枚举名{枚举列表, ,}枚举变量名;其中枚举名和变量名都是可有可无的,枚举列表默认是从0开始赋值,逐渐加一的一个符号常量的几何,也可以直接进行整型常量的赋值;作用就是 相比const和define有了enum可以更加简洁的定义很多个符号常量,更加方便;一般是需要定义多个符号常量时,例如errorcode或者需要定义常量时使用;
enum Type
{
INFO,
ERRO,
WARN,
DEBUG,
};
结构体struct首次,为什么会衍生出结构体这个东西,本身我们所学的基本类型中有一维的,就是各种变量,字符串,布尔量;二维的有数组等;但是呢由于数组中的成员都是同一数据类型,那么如果不同数据类型的集合就可以用结构体来定义了。在c++中,struct定义的后面直接是变量名;而typedef struct定义的后面是结构体类型,区别就是结构体类型需要实例化之后才能访问结构体中的成员。
c++中的struct相比c中的已经扩充了很多内容,不仅可以包含不同类型的成员变量,也可以包含成员函数、可继承、可多态,那么与class的区别就是:struct中的成员默认是public的,而class中的成员默认是private
一个 union 可以有多个数据成员,但是在任意时刻只有一个数据成员可以有值。当某个成员被赋值后其他成员变为未定义状态。
类其实也就是一种数据类型,跟结构体差不多,它的目的就是多了一层封装,类似于你写一堆函数放在一个cpp中,在别的里面再调用,类就相当于写了一堆函数,再封装一下,再把一堆的类放在一个cpp中,这样做的好处是在大项目中能够更加清晰看懂代码逻辑,方便组织管理代码。类是一种数据类型,它的实例化就叫做对象,不同于struct对应的变量就叫变量。
类中一般包括成员函数和成员变量,定义class 类名{public/private:成员变量;函数};类只是一个模板,不占用内存空间,只有实例化之后才会占内存,创建对象后可以通过对象名.成员名来访问类中的成员
指针这个东西其实就跟编程的底层有关了,其实在编程中定义的所有东西都会占用内存空间,那如果我们直接对内存空间进行修改的话,很大程度会增加编程的灵活性,这样指针就产生了,指针其实也就是个变量,本身也会占用内存空间,但是与一般变量不同的是,指针变量中存储的内容是内存空间的地址,通过这个地址,我们就可以找到这个内存空间对应的变量了
编译器常用操作 Visual Studio(VS)—Windowsvoid register(fun)
{
//新开一个线程,判断什么时候触发fun
if(...)
{
fun();
}
}
回调函数
void callback()
{
//触发回调之后要做的事情
}
主函数
int main()
{
register(callback);
return 0;
}
结构体作为形参传递参考链接
推荐链接中的第三种
int test*()
{
int *a[3]={0,1,2};
return a;
}
int main()
{
int *res;
res = test();
std::cout<< res[0]<< std::endl;
}
在C语言中,动态分配内存用 malloc() 函数,释放内存用 free() 函数;C++中使用new 和 delete:new 用来动态分配内存,delete 用来释放内存。
int *p = new int; //分配1个int型的内存空间
delete p; //释放内存
int *p = new int[10]; //分配10个int型的内存空间
delete[] p;
通常 new 和 delete、new[] 和 delete[] 操作符应该成对出现
参考链接:继承和派生
继承和派生继承是指继承方式,public\protected\private;派生是指继承了基类的派生类(也就是继承了父的子),其中父的private在子和外人中均不可访问,毕竟是爸比私人的秘密哈哈哈儿子也不可以访问的哟~而父的protected可以被子访问,外人不可访问,public那就是everyone都可以访问;另外子继承了的成员变量也可以在自己的类中变更访问方式哦
class 子类名:继承方式(public/protected/private)父类名
如果派生类中的成员(包括成员变量和成员函数)和基类中的成员重名,那么就会遮蔽从基类继承过来的成员,不会构成重载。但是,基类中的成员函数仍然可以访问,不过要加上类名和域解析符。
构造-----类的一种特殊的成员函数,它会在每次创建类的新对象时执行。构造函数可用于为某些成员变量设置初始值,名称与类名相同。
采用参数初始化表,成员变量的赋值顺序由它们在类中的声明顺序决定,初始化 const 成员变量的唯一方法就是使用参数初始化表。派生类只能采用构造函数初始化列表的方式向基类或成员对象的构造函数传递参数。
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){
//TODO:
}
构造函数必须是 public 属性的,否则创建对象时无法调用。
不管是声明还是定义,函数名前面都不能出现返回值类型,即使是 void 也不允许;
函数体中不能有 return 语句。
构造函数是允许重载的。一个类可以有多个重载的构造函数,创建对象时根据传递的实参来判断调用哪一个构造函数。
先构造基类,再构造成员,最后构造自身(调用构造函数)。
在设计派生类时,对继承过来的成员变量的初始化工作也要由派生类的构造函数完成,但是大部分基类都有 private 属性的成员变量,它们在派生类中无法访问,更不能使用派生类的构造函数来初始化。
解决这个问题的思路是:在派生类的构造函数中调用基类的构造函数。
//People(name, age)就是调用基类的构造函数
Student::Student(char *name, int age, float score): People(name, age), m_score(score){ }
定义派生类构造函数时最好指明基类构造函数;如果不指明,就调用基类的默认构造函数(不带参数的构造函数)
拷贝(复制)构造函数参考链接
当同一个类的对象2要拷贝对象1时,例如class A:
A a1(1,2,3);
A a2(a1);
当a2实例化的时候,就会调用默认的或者非默认的(程序中重新编写的)拷贝构造函数;
只有在初始化的时候才会调用拷贝构造,而在赋值语句不会引发复制构造函数的调用。(赋值语句的等号左边是一个早已有定义的变量)
析构-----它会在每次删除所创建的对象时执行。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。析构函数没有参数,不能被重载,因此一个类只能有一个析构函数。
在所有函数之外创建的对象是全局对象,它和全局变量类似,位于内存分区中的全局数据区,程序在结束执行时会调用这些对象的析构函数。
在函数内部创建的对象是局部对象,它和局部变量类似,位于栈区,在局部函数执行结束时会调用这些对象的析构函数。
new 创建的对象位于堆区,通过 delete 删除时才会调用析构函数;如果没有 delete,析构函数就不会被执行。
创建派生类对象时,构造函数的执行顺序和继承顺序相同,即先执行基类构造函数,再执行派生类构造函数。
而销毁派生类对象时,析构函数的执行顺序和继承顺序相反,即先执行派生类析构函数,再执行基类析构函数。
为了解决多继承时的命名冲突和冗余数据问题,C++ 提出了虚继承virtual,使得在派生类中只保留一份间接基类的成员。
两种创建对象的方式:一种是在栈上创建,
Student stu;
Student *pStu = &stu;
在栈上创建对象时,实参位于对象名后面,例如Student stu(“小明”, 15, 92.5f);
另外一种是在堆上创建,
Student *pStu = new Student;
delete pStu; //删除对象
栈内存是程序自动管理的,不能使用 delete 删除在栈上创建的对象;堆内存由程序员管理,对象使用完毕后可以通过 delete 删除。
成员变量大都以m_开头,这是约定成俗的写法,不是语法规定的内容。以m_开头既可以一眼看出这是成员变量,又可以和成员函数中的形参名字区分开。
根据C++软件设计规范,实际项目开发中的成员变量以及只在类内部使用的成员函数(只被成员函数调用的成员函数)都建议声明为 private,而只将允许通过对象调用的成员函数声明为 public。
给成员变量赋值的函数通常称为 set 函数,它们的名字通常以set开头,后跟成员变量的名字;读取成员变量的值的函数通常称为 get 函数,它们的名字通常以get开头,后跟成员变量的名字。
除了 set 函数和 get 函数,在创建对象时还可以调用构造函数来初始化各个成员变量。
引用的定义方式类似于指针,只是用&取代了*,语法格式为:
type &name = data;
引用必须在定义的同时初始化,并且以后也要从一而终,不能再引用其它数据,这有点类似于常量(const 变量)。
注意,引用在定义时需要添加&,在使用时不能添加&,使用时添加&表示取地址。
如果不希望通过引用来修改原始的数据,那么可以在定义时添加 const 限制,形式为:
const type &name = value;
在当前类以外定义的、不属于当前类的函数也可以在类中声明,但要在前面加 friend 关键字,这样就构成了友元函数。
友元函数不同于类的成员函数,在友元函数中不能直接访问类的成员,必须要借助对象。
class Student{
public:
Student(char *name, int age, float score);
public:
friend void show(Student *pstu); //将show()声明为友元函数
private:
char *m_name;
int m_age;
float m_score;
};
//非成员函数
void show(Student *pstu){
cout
引入内联函数的目的是为了解决程序中函数调用的效率问题,这么说吧,程序在编译器编译的时候,编译器将程序中出现的内联函数的调用表达式用内联函数的函数体进行替换,而对于其他的函数,都是在运行时候才被替代。只有当函数只有 10 行甚至更少时才将其定义为内联函数.内联该函数可以令目标代码更加高效. 对于存取函数以及其它函数体比较短, 性能关键的函数, 鼓励使用内联.
在类体中定义的成员函数会自动成为内联函数
只有类的成员函数才有 this 指针,成员函数通过一个名为 this 的额外隐式参数来访问调用它的那个对象,this就是指的调用对象
this 是 const 指针,this 只能在成员函数内部使用,用在其他地方没有意义,也是非法的
使用 static 关键字来把类成员定义为静态的,静态成员在类的所有对象中是共享的,类似于全局变量的含义
static 成员变量必须在类声明的外部初始化,具体形式为:
type class::name = value;
static 成员变量既可以通过对象来访问,也可以通过类来访问
静态成员函数静态成员函数即使在类对象不存在的情况下也能被调用,静态函数只要使用类名加范围解析运算符 :: 就可以访问。
静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数)。静态成员函数与普通成员函数的根本区别在于:普通成员函数有 this 指针,可以访问类中的任意成员;而静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数)。
#includeusing namespace std;
class A
{public:
A(int x):m_x(x){};
static void f(A a);
private:
int m_x;
};
void A::f(A a)
{//静态成员函数只能引用属于该类的静态数据成员或静态成员函数。
// cout<A a(5);
a.f(a);
// system("pause");
return 0;
}
重载运算符和重载函数重载必须满足形参的类型/个数/顺序不同,不能靠返回类型不同重载函数!
一般将功能类似的函数用于重载
重载大部分 C++ 内置的运算符,就能使用自定义类型的运算符。重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。
继承时,要养成的一个好习惯就是,基类析构函数中,加上virtual。这是为了防止内存泄漏。假设基类中采用的是非虚析构函数,当删除基类指针指向的派生类对象时就不会触发动态绑定,因而只会调用基类的析构函数,而不会调用派生类的析构函数。那么在这种情况下,派生类中申请的空间就得不到释放从而产生内存泄漏。所以,为了防止这种情况的发生,C++中基类的析构函数应采用virtual虚析构函数。
多态多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。
C++中虚函数的唯一用处就是构成多态,基类指针可以按照基类的方式来做事,也可以按照派生类的方式来做事,它有多种形态,或者说有多种表现方式,我们将这种现象称为多态。
通过基类指针只能访问派生类的成员变量,但是不能访问派生类的成员函数。
C++提供多态的目的是:可以通过基类指针对所有派生类(包括直接派生和间接派生)的成员变量和成员函数进行“全方位”的访问,尤其是成员函数。如果没有多态,我们只能访问成员变量。
有虚函数才能构成多态,这节我们来重点说一下虚函数的注意事项:
赋值的本质是将现有的数据写入已分配好的内存中,对象的内存只包含了成员变量,所以类对象之间的赋值是成员变量的赋值,成员函数不存在赋值问题。
把派生类对象赋值给基类对象。 把派生类对象的地址赋值给基类指针。 用派生类对象初始化基类对象的引用。 反之则不行,即不能把基类对象赋值给派生类对象;不能把基类对象的地址赋值给派生类对象的指针;也不能把基类对象作为派生对象的引用。这种转换关系是不可逆的,只能用派生类对象给基类对象赋值,而不能用基类对象给派生类对象赋值。
const 可以用来修饰成员变量、成员函数以及对象。如果你不希望某些数据被修改,可以使用const关键字加以限定。
const 成员函数可以使用类中的所有成员变量,但是不能修改它们的值;常成员函数需要在声明和定义的时候在函数头部的结尾加上 const 关键字
class Student{
public:
Student(char *name, int age, float score);
void show();
//声明常成员函数
char *getname() const;
int getage() const;
float getscore() const;
private:
char *m_name;
int m_age;
float m_score;
};
//定义常成员函数
char * Student::getname() const{
return m_name;
}
常对象: const定义的常对象必须进行初始化,而且不能被更新。 (类名 const 对象名 ),通过常对象只能调用它的常成员函数,普通对象调用普通成员函数
常引用:被引用的对象不能被更新。 const 类型说明符 &引用名
常数组:数组元素不能被更新。 类型说明符 const 数组名[大小]
常指针:指向常量的指针。
所谓函数模板,实际上是建立一个通用函数,它所用到的数据的类型(包括返回值类型、形参类型、局部变量类型)可以不具体指定,而是用一个虚拟的类型来代替(实际上是用一个标识符来占位),等发生函数调用时再根据传入的实参来逆推出真正的类型。这个通用函数就称为函数模板(Function Template)。
templatevoid Swap(T *a, T *b){
T temp = *a;
*a = *b;
*b = temp;
}
template
//在函数体中可以使用类型参数
}
//声明
template//这里不能有分号
class Point{public:
Point(T1 x, T2 y): m_x(x), m_y(y){}
public:
T1 getX() const; //获取x坐标
void setX(T1 x); //设置x坐标
T2 getY() const; //获取y坐标
void setY(T2 y); //设置y坐标
private:
T1 m_x; //x坐标
T2 m_y; //y坐标
};
//定义
templatevoid Point::setY(T2 y){m_y = y;
}
//实例化,在实例化时必须显式地指明数据类型,
Pointp1(10, 20);
Point*p1 = new Point(10.6, 109.3);
常用的头文件你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧