C++基础05-类构造函数与析构函数

总结:

1、类对象的作用域为两个{}之间。在遇到}后开始执行析构函数

2、当没有任何显式的构造函数(无参,有参,拷贝构造)时,默认构造函数才会发挥作用

    一旦提供显式的构造函数,默认构造函数不复存在,默认构造函数都会被覆盖掉。若想调用,则显示提供默认构造函数

3、析构函数不能重载,没有参数,没有返回值。显示提供析构,默认析构就会被覆盖掉

4、当调用默认构造函数时,类对象的数据成员值是在栈上随机分配的随机值

5、当没有显式的拷贝构造函数时,默认拷贝构造才会出现

6、每个类对象都会有默认的拷贝构造函数  但只是单纯的将一个类对象的数据成员变量赋值给本身

    //构造函数是对象初始化的时候调用
    Test t3 = t1;  //初始化t3时调用t3构造函数 依然是调用t3的拷贝构造函数
    t3.printT();

    Test t4;  //已经调用默认无参构造函数 初始化
    t4 = t1; //调用的不是t4拷贝构造函数,而是t4的赋值操作符函数

7、需要有额外空间释放时,调用析构函数。否则无需显式写出。

8、析构函数的作用,并不是删除对象,而在对象销毁前完成的一些清理工作。对象的释放是由操作系统控制(存放在栈)

9、当没有显式的析构函数时,默认析构函数被调用

10、析构函数的调用顺序 和构造相反:谁先构造,谁后析构  (栈结构)

11、当类的数据成员中有指针时,拷贝构造函数必须显式说明(为指针所存内存开辟空间)同时析构函数 手动释放空间

12、拷贝构造函数的应用场景:

   <1>Test t2 = t1; //⽤对象t1 初始化 对象 t2

   <2>Test t2(t1); //⽤对象t1 初始化 对象 t2

   <3>void func(Test p) //会执⾏ p = t1 的操作,p会调⽤copy构造函数进⾏初始化

    <4>函数的返回值是⼀个元素 (复杂类型的), 返回的是⼀个新的匿名对象(所以会调⽤匿名对象类的copy构造函数

    注意:

        有关 匿名对象的去和留

        如果⽤匿名对象 初始化 另外⼀个同类型的对象, 匿名对象 转成有名对象

        如果⽤匿名对象 赋值给 另外⼀个同类型的对象, 匿名对象 被析构

13、系统提供默认的拷贝构造器,一经定义不再提供。但系统提供的默认拷贝 构造器是 等位拷贝,也就是通常意义上的浅拷贝。如果类中包含的数据元素全部在栈上,浅拷贝 也可以满足需求的。但如果堆上的数据,则会发生多次析构行 为。

14、如果我们有一个类成员,它本身是一个类或者是一个结构,而且这个成 员它只有一个带参数的构造函数,没有默认构造函数。这时要对这个类成员进行初始化,就必须调用这个类成员的带参数的构造函数,

15、构造函数的初始化列表  初始化对象时需要用到
       构造对象成员的顺序跟初始化列表的顺序无关
       而是跟成员对象的定义顺序有关

16、在构造函数执行时,先执行初始化列表,实现变量的初始化,然后再执行函数内部的语句

17、

《C++ Primer》中提到在以下三种情况下需要使用初始化成员列表:

   情况一、需要初始化的数据成员是对象的情况(这里包含了继承情况下,通过显示调用父类的构造函数对父类数据成员进行初始化); 

   情况二、需要初始化const修饰的类成员或初始化引用成员数据;

   情况三、子类初始化父类的私有成员;

情况一的说明:数据成员是对象,并且这个对象只有含参数的构造函数,没有无参数的构造函数;

     如果我们有一个类成员,它本身是一个类或者是一个结构,而且这个成员它只有一个带参数的构造函数,而没有默认构造函数,这时要对这个类成员进行初始化,就必须调用这个类成员的带参数的构造函数,如果没有初始化列表,那么他将无法完成第一步,就会报错。

情况二的说明:对象引用或者cosnt修饰的数据成员

     情况二:当类成员中含有一个const对象时,或者是一个引用时,他们也必须要通过成员初始化列表进行初始化,因为这两种对象要在声明后马上初始化,而在构造函数中,做的是对他们的赋值,这样是不被允许的。

情况三的说明:子类初始化父类的私有成员,需要在(并且也只能在)参数初始化列表中显示调用父类的构造函数,因为只有初始化列表可以构造父类的private成员(通过显示调用父类的构造函数)

18、构造函数就是用来初始化自己数据成员的。所以先有构造函数的调用,再有数据成员的初始化(若有继承关系,先调用父类构造函数,在调用子类构造函数,再初始化数据成员,再执行构造函数中的语句。)

class Test{
public:Test(){};Test (int x){ int_x = x;};void show(){cout<< int_x << endl;}
private:int int_x;
};
class Mytest:public Test{
public:Mytest() :Test(110){//Test(110);            //  构造函数只能在初始化列表中被显示调用,不能在构造函数内部被显示调用};
};
int _tmain(int argc, _TCHAR* argv[])
{Test *p = new Mytest();p->show();return 0;
}

结果:如果在构造函数内部被显示调用输出结果是:-842150451(原因是这里调用了无参构造函数);

            如果在初始化列表中被显示调用输出结果是:110

参考自https://blog.csdn.net/sinat_20265495/article/details/53670644

17、使用构造函数初始化列表的好处:

类对象的构造顺序显示,进入构造函数体后,进行的是计算,是对成员变量的赋值操作,显然,赋值和初始化是不同的,这样就体现出了效率差异,如果不用成员初始化类表,那么类对自己的类成员分别进行的是一次隐式的默认构造函数的调用,和一次赋值操作符的调用,如果是类对象,这样做效率就得不到保障

注意:构造函数需要初始化的数据成员,不论是否显示的出现在构造函数的成员初始化列表中,都会在该处完成初始化,并且初始化的顺序和其在类中声明时的顺序是一致的,与列表的先后顺序无关,所以要特别注意,保证两者顺序一致才能真正保证其效率和准确性。
 

01构造和析构函数

# if 1
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Test {
public://test类的构造函数//在对象被创建的时候,用来初始化对象的函数Test()//无参数的构造函数{m_x = 0;m_y = 0;}Test(int x){m_x = x;m_y = 0;}Test(int x, int y) {m_x = x;m_y = y;name = (char *)malloc(100);strcpy(name, "zhangsan");}void printT(){cout << "x = " << m_x << "  y = " << m_y << endl;}//析构函数和构造函数都没有返回值,//析构函数没有形参~Test() {cout << "~Test 执行" << endl;if (name != NULL){free(name);name = NULL;cout << "free succ!" << endl;}}
private:int m_x;int m_y;char *name;
};void test01() {Test t1(10, 20);  //类对象的作用域为两个{}之间。在遇到}后开始执行析构函数t1.printT();Test t2(100);t2.printT();Test t3;//就是调用类的无参数构造函数t3.printT();cout << "操作完毕" << endl;
}int main() {test01();return 0;
}
#endif

运行结果:

02构造函数分类

# if 1
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Test {
public://test类的构造函数//在对象被创建的时候,用来初始化对象的函数Test(int x, int y) {m_x = x;m_y = y;name = (char *)malloc(100);strcpy(name, "zhangsan");}void printT(){cout << "x = " << m_x << "  y = " << m_y << endl;}//析构函数和构造函数都没有返回值,//析构函数没有形参~Test() {cout << "~Test 执行" << endl;if (name != NULL){free(name);name = NULL;cout << "free succ!" << endl;}}
private:int m_x;int m_y;char *name;
};
void test01() {//Test t1;  //报错 “Test” : 没有合适的默认构造函数可用Test t1(1, 2);  //ok
}
int main() {test01();return 0;
}#endif

运行结果:

03拷贝构造函数

# if 1
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Test {
public://test类的构造函数//在对象被创建的时候,用来初始化对象的函数Test(){m_x = 0;m_y = 0;}Test(int x, int y) {m_x = x;m_y = y;}void printT(){cout << "x = " << m_x << "  y = " << m_y << endl;}
#if 0//显示的拷贝构造函数Test(const Test &another) {  //加const表示只读。要去初始化另一个值。自己本身不能被修改m_x = another.m_x;m_y = another.m_y;cout << "调用Test(const Test &another)拷贝 " << endl;}
#endif
#if 0//会有默认的拷贝构造函数 单纯的将一个类对象的数据成员变量赋值给本身Test(const Test &another) {  m_x = another.m_x;m_y = another.m_y;}
#endif   //=赋值操作符void operator=(const Test& another) {m_x = another.m_x;m_y = another.m_y;}
private:int m_x;int m_y;
};
void test01() {Test t1(100,200);Test t2(t1);  //提供默认拷贝构造函数t2.printT();//构造函数是对象初始化的时候调用Test t3 = t1;  //初始化t3时调用t3构造函数 依然是调用t3的拷贝构造函数t3.printT();Test t4;  //已经调用默认无参构造函数 初始化t4 = t1; //调用的不是t4拷贝构造函数,而是t4的赋值操作符函数
}
int main() {test01();return 0;
}#endif

运行结果:

04拷贝构造函数的应用场景

# if 1
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Test {
public://test类的构造函数//在对象被创建的时候,用来初始化对象的函数Test() {cout << "Test()" << endl;m_x = 0;m_y = 0;}Test(int x, int y) {cout << "Test(int x, int y)" << endl;m_x = x;m_y = y;}void printT(){cout << "x = " << m_x << "  y = " << m_y << endl;}//显示的拷贝构造函数Test(const Test &another) {  //加const表示只读。要去初始化另一个值。自己本身不能被修改m_x = another.m_x;m_y = another.m_y;cout << "调用Test(const Test &another)拷贝 " << endl;}void operator=(const Test& another) {cout << "调用operator=(const Test& another) " << endl;m_x = another.m_x;m_y = another.m_y;}~Test() {cout << "~Test()...be done" << endl;}
private:int m_x;int m_y;
};
//析构函数的调用顺序 和构造相反:谁先构造,谁后析构  (栈结构)//场景1
void test01() {Test t1(10, 20);Test t2(t1);  //调用拷贝构造函数 等价于Test t2 = t1;
}
/*
运行结果:
Test(int x, int y)
调用Test(const Test &another)拷贝
~Test()...be done
~Test()...be done
*/
//场景2
void test02() {Test t1(10, 20);Test t2;t2 = t1;
}
/*
运行结果:
Test(int x, int y)
Test()
调用operator=(const Test& another)
~Test()...be done
~Test()...be done
*/
void func(Test t) {  //调用func时  Test t=t1; Test t的拷贝构造函数cout << "Func begin.." << endl;t.printT();cout << "Func end..." << endl;
}  //析构t
//场景3
void test03() {cout << "test03 begin.." << endl;Test t1(10, 20);func(t1);cout << "test03 end..." << endl;
} //析构t1
/*
运行结果:
test03 begin..
Test(int x, int y)
调用Test(const Test &another)拷贝
Func begin..
x = 10  y = 20
Func end...
~Test()...be done
test03 end...
~Test()...be done
*/
Test func2() {cout << "func2 begin..." << endl;Test temp(10, 20); temp.printT();cout << "func2 end..." << endl;return temp;  //会有 Test的匿名对象 匿名对象(temp)  temp去初始化匿名构造 匿名对象的拷贝构造
} //析构temp
//场景4
void test04() {cout << "test04 begin..." << endl;func2();  //返回一个匿名对象 当一个函数返回匿名对象时,//如果函数外部没有任何变量去接收它,这个匿名对象将不会再被使用//编译器会直接将这个匿名对象回收掉,而不是等待整个函数执行完毕后再回收//匿名对象被回收cout << "test04 end..." << endl;
}
/*
运行结果:
test04 begin...
func2 begin...
Test(int x, int y)
x = 10  y = 20
func2 end...
调用Test(const Test &another)拷贝
~Test()...be done
~Test()...be done
test04 end...
*///场景5
void test05() {cout << "test05 begin..." << endl;Test t1=func2();   //会不会触发t1的拷贝构造函数   t1.拷贝(匿名) //不会触发 将匿名对象转正为t1//给匿名对象 起了个名字就叫t1cout << "test05 end..." << endl;
}  //析构t1
/* 
运行结果:
test05 begin...
func2 begin...
Test(int x, int y)
x = 10  y = 20
func2 end...
调用Test(const Test &another)拷贝
~Test()...be done
test05 end...
~Test()...be done
*///场景6
void test06() {cout << "test06 begin..." << endl;Test t1;  //t1已经被初始化t1 = func2();    //匿名对象赋值给t1,匿名对象并没有转正,所以即刻析构cout << "test06 end..." << endl;
}
/*
运行结果:
test06 begin...
Test()
func2 begin...
Test(int x, int y)
x = 10  y = 20
func2 end...
调用Test(const Test &another)拷贝
~Test()...be done
调用operator=(const Test& another)
~Test()...be done
test06 end...
~Test()...be done
*/
int main() {//test01();//test02();//test03();//test04();//test05();test06();return 0;
}#endif

05深拷贝与浅拷贝应用场景

防止内存泄漏(开辟的空间没有释放):导致内存爆掉 程序崩溃

防止释放同一块内存

当类的数据成员中有指针时,拷贝构造函数必须显式说明(为指针所存内存开辟空间)

同时析构函数 手动释放空间

# if 1
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Teacher {
public:Teacher(int id, char *name) {cout << "Teacher(int id, char *name)" << endl;m_id = id;int len = strlen(name);m_name = (char*)malloc(len + 1);  //strlen长度计算不包括'\0' 所以此处加一strcpy(m_name, name);}void printT() {cout << "m_id:"<< m_id << " m_name : " << m_name << endl;}//默认拷贝构造函数Teacher(const Teacher &another) {m_id = another.m_id;m_name = another.m_name;  //指向同一块内存空间}~Teacher(){cout << "~Teacher()...." << endl;if (m_name != NULL) {free(m_name);}}
private:int m_id;//char m_name[64];  没有深拷贝 浅拷贝分解 因为此时m_name在栈上分配空间char *m_name;
};void test01() {Teacher t1(1, "zhangsan");t1.printT();Teacher t2(t1);  //调用t2的默认拷贝构造  程序崩溃t2.printT();
}  //t2析构 清空zhangsan所在空间 //t1析构时 也要清空zhangsan所在空间 然而已经清空 所以程序崩溃
int main()
{test01();return 0;
}
#endif

上述程序崩溃原因如下: 

上述程序崩溃的主要原因就是默认拷贝构造函数的浅拷贝。所以使拷贝构造函数为深拷贝即可解决问题

程序如下:

# if 1
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Teacher {
public:Teacher(int id, char *name) {cout << "Teacher(int id, char *name)" << endl;m_id = id;int len = strlen(name);m_name = (char*)malloc(len + 1);  //strlen长度计算不包括'\0' 所以此处加一strcpy(m_name, name);}void printT() {cout << "m_id:"<< m_id << " m_name : " << m_name << endl;}
#if 0//默认拷贝构造函数Teacher(const Teacher &another) {m_id = another.m_id;m_name = another.m_name;}
#endif//显式提供拷贝构造函数 完成深拷贝动作Teacher(const Teacher &another) {m_id = another.m_id;int len = strlen(another.m_name);m_name = (char *)malloc(len + 1);strcpy(m_name, another.m_name);}~Teacher(){cout << "~Teacher()...." << endl;if (m_name != NULL) {free(m_name);}}
private:int m_id;//char m_name[64];  没有深拷贝 浅拷贝分解 因为此时m_name在栈上分配空间char *m_name;
};void test01() {Teacher t1(1, "zhangsan");t1.printT();Teacher t2(t1);  //调用t2的默认拷贝构造  程序崩溃t2.printT();
}  //t2析构 清空zhangsan所在空间 //t1析构时 也要清空zhangsan所在空间 然而已经清空 所以程序崩溃
int main()
{test01();return 0;
}
#endif

运行结果: 

不出错原因:

06构造函数的初始化列表

#include<iostream>
using namespace std;
class A
{
public:A(int a){cout << "A()..." << a << endl;m_a = a;}~A() {cout << "~A()" << endl;}void printA() {cout << "a = " << m_a << endl;}private:int m_a;
};
class B {
public:
#if 0B(int b, A &a1, A &a2) {//m_a1 = a1;  //赋值编译错误 //m_a2 = a2;   //m_a2(a2);  拷贝构造 编译错误  m_b = b;}
#endif/*构造函数的初始化列表  初始化对象时需要用到构造对象成员的顺序跟初始化列表的顺序无关而是跟成员对象的定义顺序有关*/B(A &a1, A &a2, int b) :m_a1(a1), m_a2(a2) {  //调用拷贝构造cout << "B(A&, A&, int)..." << endl;m_b = b;}B(int a1, int a2, int b) : m_a2(a2) ,m_a1(a1)  //调用有参构造{cout << "B(int, int, int)..." << endl;m_b = b;}void printB() {cout << "b = " << m_b << endl;m_a1.printA();m_a2.printA();}~B(){cout << "~B().." << endl;}
private:A m_a1;A m_a2;int m_b;
};void test01() {A a1(10),a2(100);B b(a1, a2, 1000);b.printB(); //b析构 b中A A析构 test01中a1 a2释放
}
/*
A()...10
A()...100
B(A&, A&, int)...
b = 1000
a = 10
a = 100
~B()..
~A()
~A()
~A()
~A()
*/
void test02() {B b(10, 20, 1000);b.printB();//b析构 b中A A析构 test01中a1 a2释放
}
/*
A()...10
A()...20
B(int, int, int)...
b = 1000
a = 10
a = 20
~B()..
~A()
~A()
*/
int main() {//test01();test02();return 0;
}

练习1(构造函数和析构函数的执行时间)

#if 0
#include<iostream>
using namespace	std;
class	ABCD
{
public:ABCD(int	a, int	b, int	c){_a = a;_b = b;_c = c;printf("ABCD()	construct,	a:%d,b:%d,c:%d \n", _a, _b, _c);}~ABCD(){printf("~ABCD()	construct,a:%d,b:%d,c:%d \n", _a, _b, _c);}int	getA(){return	_a;}
private:int	_a;int	_b;int	_c;
};
class	MyE
{
public:MyE() :abcd1(1, 2, 3), abcd2(4, 5, 6), m(100){cout << "MyD()" << endl;}~MyE(){cout << "~MyD()" << endl;}MyE(const	MyE	&	obj) :abcd1(7, 8, 9), abcd2(10, 11, 12), m(100){printf("MyD(const	MyD	&	obj)\n");}
public:ABCD	abcd1;	//c++编译器不知道如何构造abc1ABCD	abcd2;const int	m;
};
int	doThing(MyE	mye1)
{printf("doThing()	mye1.abc1.a:%d \n", mye1.abcd1.getA());return 0;
}
int	run()
{MyE	myE;doThing(myE);return 0;
}
/*
ABCD()  construct,      a:1,b:2,c:3
ABCD()  construct,      a:4,b:5,c:6
MyD()
ABCD()  construct,      a:7,b:8,c:9
ABCD()  construct,      a:10,b:11,c:12
MyD(const       MyD     &       obj)
doThing()       mye1.abc1.a:7
~MyD()
~ABCD() construct,a:10,b:11,c:12
~ABCD() construct,a:7,b:8,c:9
~MyD()
~ABCD() construct,a:4,b:5,c:6
~ABCD() construct,a:1,b:2,c:3
*/
int	run2()
{printf("run2	start..\n");ABCD(400, 500, 600);	//临时对象的⽣命周期printf("run2	end\n");return 0;
}
/*
run2    start..
ABCD()  construct,      a:400,b:500,c:600
~ABCD() construct,a:400,b:500,c:600
run2    end
*/
int	run3()
{printf("run2	start..\n");ABCD abcd=ABCD(100,	200,	300);printf("run2	end\n");return 0;
}
/*
run2    start..
ABCD()  construct,      a:100,b:200,c:300
run2    end
~ABCD() construct,a:100,b:200,c:300
*/
int	main(void)
{//run();//run2();run3();return 0;
}
#endif

练习2:

#include<iostream>
using namespace	std;
//构造中调⽤构造是危险的⾏为
class	MyTest
{
public:MyTest(int	a, int	b, int	c){_a = a;_b = b;_c = c;}MyTest(int	a, int	b){_a = a;_b = b;MyTest(a, b, 100);	//产⽣新的匿名对象}~MyTest(){printf("MyTest~:%d,	%d,	%d\n", _a, _b, _c);}int	getC(){return	_c;}void	setC(int	val){_c = val;}
private:int	_a;int	_b;int	_c;
};
int	main()
{MyTest	t1(1, 2);printf("c:%d\n", t1.getC());	//请问c的值是?return 0;
}
/*
MyTest~:1,      2,      100
c:-858993460
MyTest~:1,      2,      -858993460
*/

父类子类构造函数调用顺序

#include<iostream>
#include<string>
using namespace std;
class A
{
public:A() {std::cout << "cons A" << std::endl;}A(int i) {m_i = i;cout << "cons A with" << i << endl;}~A() {std::cout << "des A with" << m_i<< endl;}int m_i = 0;
};
# if 0
class B :public A {
public:B(){m_i = 3;cout << "cons B" << endl;}~B() {cout << "des B with" << m_i << endl;m_i = 4;}
private:A a1;A a2;
};
int main() {B b;return 0;
}
/*
cons A
cons A
cons A
cons B
des B with3
des A with0
des A with0
des A with4构造函数就是初始化数据成员的。所以现有构造函数的调用,再有数据成员的初始化
*/#endif# if 0
class B :public A {
public:B():a1(1),a2(2){m_i = 3;cout << "cons B" << endl;}~B() {cout << "des B with" << m_i << endl;m_i = 4;}
private:A a1;A a2;
};
int main() {B b;return 0;
}
/*
cons A
cons A with1
cons A with2
cons B
des B with3
des A with2
des A with1
des A with4
构造函数就是初始化数据成员的。所以现有构造函数的调用,再有数据成员的初始化
*/#endif# if 1
class B :public A {
public:B(){m_i = 3;cout << "cons B" << endl;}~B() {cout << "des B with" << m_i << endl;m_i = 4;}
};
int main() {B b;return 0;
}
/*
cons A
cons B
des B with3
des A with4
因为m_i 本身就是B从A继承而来,所以B中对m_i做更改,A也能感知到
*/#endif

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/567892.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PHP网站配置项,Thinkphp5通用网站后台配置项的动态添加及更新

一、引入无论平时我们自己制作&#xff0c;还是浏览别人的网站&#xff0c;它都具有其相应的一些共用的、通用的属性&#xff0c;比如&#xff1a;网站的名字&#xff0c;关键字、备案号、分页数量、是否开启缓存等信息。一些网站可能将配置项写死在后台&#xff0c;无法动态更…

oracle 查询cpu 100%,Oracle 11g中查询CPU占有率高的SQL

oracle版本&#xff1a;oracle11g背景&#xff1a;今天在Linux中的oracle服务上&#xff0c;运用top命令发现许多进程的CPU占有率是100%。操作步骤&#xff1a;以进程PID:7851为例执行以下语句&#xff1a;方法一&#xff1a;(1)通过PID&#xff0c;查得相对应的系统进程对应的…

C++基础08-this指针-const修饰成员函数-函数返回引用/值

一、this指针 1、C类对象中的成员变量和成员函数是分开存储的。C语言中的内存四区模型仍然有效&#xff01; 2、C中类的普通成员函数都隐式包含一个指向当前对象的this指针。 3、静态成员函数、成员变量属于类 4、静态成员函数与普通成员函数的区别 静态成员函数不包含指…

C++基础09-货物售卖和MyArray实现

1、货物出货与进货 #if 0 #include<iostream> using namespace std; /* 某商店经销一种货物。货物购进和卖出时以箱为单位。各箱 的重量不一样&#xff0c;因此商店需要记录目前库存的总重量&#xff0c;现在用 C模拟商店货物购进和卖出的情况 */ class Goods { public:…

C++基础11-类和对象之操作符重载1

总结&#xff1a; 1、运算符重载的本质是函数重载 2、运算符重载可分为成员函数重载和全局函数重载(差一个参数) 3、运算符重载函数的参数至少有一个是类对象&#xff08;或类对象的引用&#xff09; 4、不可以被重载的操作符有&#xff1a;成员选择符(.) 成员对象选择符(.*) …

linux照片备份软件,Linux、Unix上5个惊艳开源备份软件

Linux和类Unix系统上5个惊艳的开源备份软件&#xff1a;Bacula、Amanda、Backupninja、Backuppc和UrBackup&#xff0c;这些都是既可以使用在Linux上也可以使用在Unix上面&#xff0c;他们的优点就是性能稳定&#xff0c;使用灵活。一个好的备份计划是非常必要的&#xff0c;这…

linux 添加重定向域名,Linux系统中Nginx的安装并进行域名认证和重定向

Linux系统中Nginx的安装并进行域名认证和重定向本文主要介绍Linux系统中Nginx的安装并进行域名认证和重定向&#xff0c;希望通过本知识点的讲解对大家今后的学习和工作有所帮助&#xff0c;下面进行具体介绍&#xff1a;12.6 Nginx安装cd /usr/local/srcwget http://nginx.org…

linux有读EC RAM的工具吗,Step to UEFI (179)Shell下 EC Ram 读取工具

最近工作需要在 UEFI Shell 下Check EC Ram 的设定&#xff0c;发现手上只有 Windows 下的读取工具(RW Everything)。于是研究了一下如何在Shell 读取 EC Ram。根据【参考1】读取的流程如下&#xff1a;Port 66 CommandsThere are also some EC commands that use ports 0x66 …

C++基础13-类和对象之继承1

在 C中可重用性(software reusability)是通过继承(inheritance)这一机制来实现的。 如果没有掌握继承性,就没有掌握类与对象的精华。 总结&#xff1a; 1、只要是父类中的private成员&#xff0c;不管是什么继承方式&#xff0c;儿子都访问不了&#xff0c;但它是存在在儿子之…

C++基础13-类和对象之继承2

总结&#xff1a; 1、子类对象可以当做父类对象使用 2、子类对象可以直接赋值给父类对象 3、子类对象能够直接初始化父类对象 4、父类指针可以直接指向子类对象 5、凡是继承过来的属性和函数都可以在子类中用this-> 进行访问 6、默认构造函数并不会初始化数据成员 7、如果…

C++基础14-类和对象之多继承与虚继承

多继承&#xff1a;一个类有多个直接基类的继承关系称为多继承 总结&#xff1a; 1、一般将具有菱形样式继承方式的某些类声明为虚继承 3、虚继承的主要目的是为了防止二义性 2、虚继承就是在继承方式前加virtual 如果一个派生类从多个基类派生&#xff0c;而这些基类又有一…

linux系统安装ntp,CentOS下NTP安装配置

安装yum install ntp配置文件 /etc/ntp.confrestrict default kod nomodifynotrap nopeer noqueryrestrict -6 default kod nomodify notrap nopeer noqueryrestrict 127.0.0.1restrict -6 ::1# 用restrict控管权限# nomodify - 用户端不能更改ntp服务器的时间参数# noquery - …

C++基础15-类和对象之多态

总结&#xff1a; 1、在父类中申明虚函数时&#xff0c;一般情况下在子类中也申明&#xff08;便于读代码&#xff09; 一、赋值兼容 赋值兼容规则是指在需要基类对象的任何地方都可以使用公有派生类的对象来替代。 赋值兼容是一种默认行为,不需要任何的显示的转化步骤。 …

傲云浏览器linux,Centos7安装部署zabbix监控软件

目录部署监控服务器部署监控服务器Zabbix ServerWeb页面验证设置部署监控服务器一、安装LNMP环境Zabbix监控管理控制台需要通过Web页面展示出来&#xff0c;并且还需要使用MySQL来存储数据&#xff0c;因此需要先为Zabbix准备基础LNMP环境。1. wget下载官网Nginxwget http://ng…

c语言环境变量的作用,C语言获取系统环境变量

C语言获取系统环境变量可以通过如下代码实现.#include #include char *platform(){//获取系统变量信息char *ret;extern char **environ;char **env environ;//打印系统变量信息/*while(*env){//puts(*env);env;}*/ret getenv("OS"); //for windows_ntif(NULL ! re…

mysql索引创建及使用注意事项

总结&#xff1a; 1、在使用索引时&#xff0c;一般情况下不建议使用like操作。如果使用&#xff0c;则%放在后面。否则不会使用索引。like ‘%abd%’不会使用索引,而like ‘aaa%’可以使用索引.&#xff08;最左缀原则&#xff09; 2、单列索引的使用&#xff1a; 《1》 只…

mulitpartfile怎么接收不到值_和平精英信号接收区和信号值是什么?信号值怎么恢复...

[闽南网]和平精英公测开启&#xff0c;和平精英与刺激战场有什么不同呢&#xff1f;今天小编就为大家带来了信号值详解&#xff01;各位玩家千万不要错过呀&#xff01;信号值详解信号接收区和信号值是什么&#xff0c;对选手有什么影响&#xff1f;在游戏战斗界面中&#xff0…

制备pdms膜的方法_船体用钢板基底超疏水表面的制备和性能

鲨鱼皮具有神奇的微纳双层结构&#xff0c;其微米级肋条状结构在水中的整流效果可减小水的阻力。纳米级刺状突起或刚毛具有疏水特性&#xff0c;使植物抱子很难附着其上&#xff0c;海藻等植物也不能在其表面生长&#xff3b;1,2&#xff3d;。这种微纳结构及其疏水性的共同作用…

递归题型解析

#include<iostream> using namespace std; int foo(int n) {if (n < 1)return n;return (foo(n - 1) foo(n - 2)); } int main() {printf("%d\n", foo(5));return 0; } 解析&#xff1a; foo(5)foo(4)f00(3)foo(3)foo(2)foo(3)2foo(3)foo(2)2(foo(2)foo(1…

64位c语言调用32位glibc,glibc fclose源代码阅读及伪造_IO_FILE利用fclose实现任意地址执行...

简介最近学习了一下_IO_FILE的利用&#xff0c;刚好在pwnable.tw上碰到一道相关的题目。拿来做了一下&#xff0c;遇到了一些困难&#xff0c;不过顺利解决了&#xff0c;顺便读了一波相关源码&#xff0c;对_IO_FILE有了更深的理解。文章分为三部分&#xff0c;分别是利用原理…