c++面向对象三大特征封装、继承和多态知识总结

2023-11-08

面向对象三大特征:封装,继承,多态;

一、封装:该公开的就公开话,该私有的就隐藏掉,主要是由publicprivate实现;作用是便于分工和分模块,防止不必要的扩展;

二、继承:就是一种传承,可以把父类型中的数据传承到子类中,子类除了传承了父类的数据之外,还可以对父类型进行扩展;

公开继承  public

保护继承  protected

私有继承  private

保护成员:在子类和本类中可以访问,其他不行;


1、公开继承:在公开继承下,父类型中的数据是公开的到子类型中权限是公开的;父类型中保护权限的数据到子类中是保护的;父类中私有的数据到子类中会隐藏掉(就是说看不见权限,但是实际上式在子类中的);

2、私有继承:在私有继承下,父类中的公开数据到子类中变成私有的,父类中的保护数据到子类中称为私有的,父类中的私有数据到子类中隐藏;

3、保护继承:保护继承下,父类中的公开数据和保护数据到了子类中都成为保护权限,父类中私有的数据到了子类中就变成了隐藏的;


4、注意:不管何种类型的继承关系,父类私有成员到子类中都成为了隐藏掉。

公开继承下的public成员和protected成员的权限变化:

#include <iostream>
using namespace std;

class A{
public:
	int a;
	int geta(){
		a = 300;
		return a;
	}
	/*保护类型成员在本类和子类中可以访问*/
protected:
	int b;
private:
	int c;
};

class B:public A{
	//int x;
public:
	void getb(){
		b = 200;
	}
	void show(){
		cout << b << endl;
	}
	void showa(){
		cout<< a<<endl;
	}
}; 
/*关键在于如何设置接口,成功合理的访问到各种类型的数据*/
int main(){
	B pex;
	/*公开继承public成员依旧是public,所以可以类外访问*/
	pex.a = 100;
	/*b是保护类型成员,可以通过设置public接口来访问*/
	pex.getb();
	pex.show();
	/*隐藏成员的问题,怎么访问到隐藏的成员*/
	pex.geta();
	pex.showa();
	//A a = pex;//子类类型赋给了父类类型
	//a.geta();
	//cout << a.a << endl;
}


5、私有继承下的成员的权限变化关系,注意如何设置合理的 访问接口去访问 隐藏的数据成员。

/*私有继承下的权限变化,关键是设置合理的接口访问
父类中的各种类型的数据成员*/
#include <iostream>
using namespace std;

class A{
private:
	void showa(){
		cout << "this is showa()" << endl;
	}
protected:
	void showb(){
		cout << "this is showb" << endl;
	}
public:
	void showc(){
		cout << "this is showc" << endl;
	}
	void geta(){//设置合理的接口访问A中的私有数据
		showa();
	}
};

class B:private A{
public:
	void show(){
		showc();
		showb();
		geta();
	}
};

int main(){
	B b;
	//A a = b;对比公开继承,对比一下
	b.show();
}

6、突破成员访问权限,可以设置合理的访问接口,也可以使用友元类。

/*友元类*/
#include <iostream>
using namespace std;

class A{
private:
	int x;
	int y;
public:
	A():x(10),y(123){}
	/*B,C声明为A的友元类之后,可以访问到父类的所有类型成员*/
	friend class B;
	friend class C;
};

class B:public A{
public:
	void show(){
		cout << x << "---" << y << endl; 
	}
};

class C{
public:
	void show(){
		A a;
		cout <<a.x<< "---" << a.y << endl;
	}
};

int main(){
	B b;
	b.show();
	C c;
	c.show();
}

7、继承中构造函数、析构函数、赋值运算符函数和拷贝构造函数

构造函数和析构函数是不能被继承的,但是可以被调用。并且子类一定会调用父类的构造函数;

子类默认调用父类的无参构造,也可以制定调用构造函数;

析构函数的调用和构造函数的调用顺序相反;

拷贝构造函数和赋值运算符函数也不能被继承:在子类不提供拷贝构造和赋值运算符时,子类默认调用父类的赋值运算符和拷贝构造函数。但子类一旦提供拷贝构造和赋值运算符函数则不再调用父类拷贝构造和赋值运算符函数。

/*继承中构造函数和析构函数的调用:构造函数和析构函数不可以
被继承,但是可以被调用,而且子类肯定会调用父类的构造函数
和析构函数。这种机制可以很自然的用于访问父类的私有成员*/
#include <iostream>
using namespace std;

class A{
private:
	int x;
public:
	//A(){cout << "A()" << endl;}
	A(int x = 0):x(x){
		cout <<"A()构造"<<endl;
		cout << x << endl;}
	~A(){cout << "~A()" << endl;}
	int _get(){
		return x;
	}
};

class B:public A{
public:
	/*在初始化参数列表中可以指定调用父类的构造函数,指定调用构造函数并且给
	父类中的私有成员赋值*/
	/*注意:子类默认调用父类的无参构造,如果下面的代码没有:A(100),则会调用无参构造,但是父类无参构造
	被注释掉,所以会出错*/
	B():A(100){
		//x = 200;
		//A(100);
		cout << "B()" << endl;
	}
	//访问有参构造的方式,理解这种方式的作用
	/*注意,这种机制下的构造函数所赋的值是赋到了子类中的数据x中,
	而父类中的x仍然为0*/
	~B(){cout << "~B()" << endl;}
	int getbx(){
		return _get();
	}
};
int main(){
	A a;//构建A对象,此时A类构造被调用,并打印出了值

	B b;//B类为无参构造,首先调用了A的构造,在调用B的构造

	//打印a对象中的x成员
	cout <<a._get()<<endl;//a对象中的x为0

	//打印b对象中的x
	cout << b.getbx()<<endl;//是100
	/*一层一层的退,先调用b的析构,在调用a的析构*/
}
拷贝构造和赋值运算符的问题

#include <iostream>
using namespace std;
/*系统一旦提供构造函数,系统默认的构造函数将被回收
记住,拷贝构造也是构造函数*/
class A{
	int arr;
public:
	A(){}
	//A(int x = 0):arr(x){}
	A(const A& a){
		cout << "父类拷贝构造" << endl;
	}
	void operator=(const A& a){
		cout << "父类赋值运算符函数" << endl;
	}
};
/*有指针类型的成员时,采用默认机制就麻烦了*/
class B:public A{
	//int * pi;
public:
	B(){}
	B(const B& b):A(b){                      
		//子类中提供了拷贝构造函数将不再调用父类的拷贝构造
		cout << "子类拷贝构造" << endl;
	}
	void operator=(const B& b){
		A::operator=(b);         //调用父类的拷贝构造函数的机制
		cout << "子类赋值运算符函数"<< endl;
	}
};

int main(){
	B a;
	B b = a;
	B c;
	c = a;
}

8,名字隐藏

名字隐藏机制:子类中如果定义了和父类中同名的数据,这些数据包括成员变量和成员函数。则会把父类中的数据隐藏掉。

注意:只要名字相同,计算返回值或者形参列表不同,也会被隐藏。隐藏不代表就没有了,可以通过类名作用域::访问到被隐藏的成员。

#include <iostream>
using namespace std;

class A{
public:
	int x;
	int show(){
		cout << "show A" << endl;
		return 0;
	}
	A(){x=20;}
	A(int x):x(x){cout << "show A(int x)" << endl;}
	void shouu(){
		cout <<"shouu()"<<endl;
	}
};

class B:public A{
public:
	int x;
	int y;
	B(){cout << "B()" << endl;}
	void show(){
		cout << "show B" << endl;
		//A::show();
	}
};

int main(){
	B b;
	b.shouu();
	//cout << b.x << endl;
	//cout << b.A::x << endl;   //突破名字隐藏机制
	//int c = b.show();被隐藏,无法访问
	//b.A::show();
}

9、多继承和函数重写

多继承是c++特有的语法机制,表现为一个子类有多个直接的父类。

#include <iostream>
using namespace std;

class phone{
	double price;
public:
	//phone();
	phone(double price = 15):price(price){cout << "phone" << endl;}
	~phone(){cout << "~phone" << endl;}
	void call(){
		cout << "use calling" << endl;
	}
	double getprice(){
		return price;
	}
};

class MP3{
	double price;
public:
	MP3(double price = 20):price(price){cout << "MP3" << endl;}
	~MP3(){cout << "~MP3" << endl;}
	void play(){
		cout << "use to listening music" << endl;
	}
	double getprice(){
		return price;
	}
}; 

class vedio{
	double price;
public:
	vedio(double price = 0):price(price){cout << "vedio" << endl;}
	~vedio(){cout << "~vedio" << endl;}
	void vcd(){
		cout << "watch vedio" << endl;
	} 
	double getprice(){
		return price;
	}
};
/*多继承*/
class iphone:public phone,public MP3,public vedio{
public:
	double getprice(){
		return phone::getprice() + MP3::getprice() + vedio::getprice();
	}
};

int main(){
	iphone iphone6;
	//cout << sizeof(iphone) << endl;
	cout << iphone6.MP3::getprice() << endl;
	cout << iphone6.phone::getprice() << endl;
	cout << iphone6.getprice() << endl;    //用名字隐藏机制解决多分数据同名冲突的问题
}

多继承遇到的问题:上面的代码用sizeof就可以看到,子类在多继承的时候会多次复制顶层数据,而我们期望的是price这个成员只需要复制一份就可以了,因为多余的复制是无意义的。首先采用顶层抽象的方式,将三个父类抽象到更高的层面上。

#include <iostream>
using namespace std;
/*抽象到更高层的类中*/
class product{
	double price;
public:
	double getprice(){
		return price;
	}
	product(double price = 0):price(price){cout <<"product"<<endl;}
};
class phone:public product{
public:
	//phone();
	phone(double price = 15):product(price){cout << "phone" << endl;}
	~phone(){cout << "~phone" << endl;}
	void call(){
		cout << "use calling" << endl;
	}
};

class MP3:public product{
public:
	MP3(double price = 20):product(price){cout << "MP3" << endl;}
	~MP3(){cout << "~MP3" << endl;}
	void play(){
		cout << "use to listening music" << endl;
	}
}; 

class vedio:public product{
public:
	vedio(double price = 0):product(price){cout << "vedio" << endl;}
	~vedio(){cout << "~vedio" << endl;}
	void vcd(){
		cout << "watch vedio" << endl;
	} 
};
class iphone:public phone,public MP3,public vedio{
	
};

int main(){
	iphone iphone6;
	//cout << iphone6.getprice() << endl;同样会产生冲突的问题
	//cout << sizeof(iphone) << endl;
	cout << iphone6.MP3::getprice() << endl;
	cout << iphone6.phone::getprice() << endl;
	//cout << iphone6.getprice() << endl;//直接调用产生冲突问题,编译器不知道该调用哪一个
}
上面的代码中,product的构造函数 被调用了三次,因为这种继承是一级一级的来的,构造子类的时候找父类,发现父类还有父类,就去调用爷爷类的构造函数,三次继承,三次调用。


这种继承方式构成了一种菱形或者钻石型的继承,叫做菱形继承或者钻石继承,但钻石继承并没有实际解决数据多次复制的问题,为了解决菱形继承,c++提出了虚继承。虚继承就是在继承的时候加上virtual关键字修饰即可。虚继承对于共同的成员父亲类从爷爷类那里继承来的,这里为double price,子类直接越级访问,直接从爷爷类那里继承price。

/*类中也会有对齐和补齐*/
#include <iostream>
using namespace std;
/*抽象到更高层的类中*/
class product{
	int price;
public:
	int  getprice(){
		return price;
	}
	product(double price = 0):price(price){cout << "product" << endl;}
};

class phone:virtual public product{
public:
	//phone();
	phone(double price = 15):product(price){cout << "phone" << endl;}
	~phone(){cout << "~phone" << endl;}
	void call(){
		cout << "use calling" << endl;
	}
};

class MP3:virtual public product{
public:
	MP3(double price = 20):product(price){cout << "MP3" << endl;}
	~MP3(){cout << "~MP3" << endl;}
	void play(){
		cout << "use to listening music" << endl;
	}
}; 

class vedio:virtual public product{
public:
	vedio(double price = 0):product(price){cout << "vedio" << endl;}
	~vedio(){cout << "~vedio" << endl;}
	void vcd(){
		cout << "watch vedio" << endl;
	} 
};
class iphone:virtual public phone,virtual public MP3,virtual public vedio{
public:
	iphone(int m = 0,int v = 0,int p = 0):product(m + p + v){}
};
/*虚函数之后,product的构造函数只被调用了一次,孙子类直接越级访问
了product类*/
int main(){
	iphone iphone6(1000,2041,3201);
	//cout << iphone6.getprice() << endl;同样会产生冲突的问题
	//cout << sizeof(iphone) << endl;
	//cout << iphone6.MP3::getprice() << endl;
	//cout << iphone6.phone::getprice() << endl;
	//cout << iphone6.getprice() << endl;直接调用产生冲突问题,编译器不知道该调用哪一个
	cout << sizeof(iphone) << endl;
	cout << iphone6.getprice() << endl;
}

这个代码中product的构造函数只调用了一次,说明子类直接越级访问了爷爷类的数据。而对于父类特有的子类照常继承,只是没有通过父类去继承爷爷类的数据成员,所以product的构造函数只被调用了一次。


虚函数:在函数前面加上virtual关键字修饰过的就是虚函数.

#include <iostream>
using namespace std;
class A{
int x;
public:
virtual void show(){}
virtual void showa(){}
};
int main(){
cout << sizeof(A) << endl;
}

虚函数的主要表现为会占用四个字节的空间,只要成员中出现虚函数,不管有多少个虚函数,都只用四个字节来维护这个虚关系。虚函数会影响对象的大小。维护虚关系使用一个指针来维护的,所以是四个字节。


函数重写:

在父类中出现一个虚函数,如果在子类中提供和父类同名的函数(注意区分名字隐藏),这就加函数重写。

函数重写要求必须有相同函数名,相同的参数列表,相同的返回值。


三、c++面向对象之多态

1、多态:一个父类型的对象的指针或者引用指向或者是引用一个子类对象时,调用父类型中的虚函数,如果子类覆盖了虚函数,则调用的表现是子类覆盖之后的。

继承是构成多态的基础;

虚函数是构成多态的关键;

函数覆盖是构成多态的必备条件;

多态的应用:函数参数,函数返回值。

多态的产生必须依靠上面的四点,缺一不可。


2、多态的应用,多态相对做到了通用类型编程,主要用在函数参数和函数的返回值上。

/*多态的应用:
1、函数参数
2、函数返回值*/
#include <iostream>
using namespace std;
class Animal{
public:
	virtual void run(){
		cout <<"Ainimal run()"<<endl;
	}
	void show(){
		cout <<"Animal show()"<<endl;
	}
};

class Dog:public Animal{
public:
	void run(){
		cout <<"Dog run()"<<endl;
	}
	void show(){
		cout <<"dog show()"<<endl;
	}
};

class Cat:public Animal{
public:
	void run(){
		cout <<"cat run()"<<endl;
	}
};
/*多态用作函数参数*/
void showAnimal(Animal * animal){
	animal->show();
	animal->run();
}
/*多态用作返回值*/
Animal * getAnimal(int x){
	if (1 == x)
		return new Dog();
	if (2 == x)
		return new Cat();
}
int main(){
	Cat cat;
	showAnimal(&cat);
	Dog dog;
	showAnimal(&dog);
}

3、多态的实现原理

多态的实现主要依赖于下面的三个东西:

虚函数:成员函数加了virtual修饰

虚函数表指针:一个类型有虚函数,则对这个类型提供一个指针,这个指针放在生成对象的前四个字节。同类型的对象共享一张虚函数表。并且不同类型的虚函数表地址不同。

虚函数表:虚函数表中的每个元素都是虚函数的地址。

一个类型一旦出现虚函数,则会生成一张虚函数表,虚函数表中存放的就是虚函数的函数地址,通过这个函数地址可以到代码区中去执行对应的函数。虚函数表中只存放类型中的虚函数,不是虚函数的一概不管。在每个生成的类型对象的前四个字节中存放的是虚函数表指针,通过这个指针可以访问到虚函数表,从而访问其中的函数。同种类型共享虚函数表,不同类型有自己独立的虚函数表,继承关系中的子类和父类属于不同类型,所以有自己独立的函数表。


/*多态的原理*/
#include <iostream>
#include <cstring>
using namespace std;
class Animal{
	int x;
public:
	virtual void fun(){
		cout<< "Aniaml fun()"<<endl;
	}
	virtual void run(){
		cout <<"Animal run()"<<endl;
	}
	void show(){
		cout <<"Animal show()"<<endl;
	}
};

class Dog:public Animal{
public:
	virtual void fun(){
		cout << "dog run"<<endl;
	}
	void run(){
		cout <<"dog run"<<endl;
	}
};

class Cat:public Animal{
public:
	void fun(){
		cout <<"cat fun"<<endl;
	}
};

int main(){
	Animal a;
	Animal b;
	/*取出虚函数表的地址并打印*/
	int * pi = (int*)&a;
	cout <<showbase<< hex << *pi<<endl;

	pi = reinterpret_cast<int*>(&b);
	cout <<showbase<< hex << *pi<<endl;

	/*子类不会和父类共享虚函数表,地址不一样*/
	Dog dog;
	pi = reinterpret_cast<int*>(&dog);
	cout <<showbase<< hex << *pi<<endl;

	Animal * pcat = new Cat();
	pcat->run();
	pcat->fun();

	/*更改dog的虚表的值,我们把dog的虚表地址
	改成cat的虚表地址*/
	Animal * pdog = new Dog();
	pdog->run();
	pdog->fun();

	/*更换dog的虚表地址,将cat的前四个字节
	移动到dog的前四个字节*/
	memcpy(pdog,pcat,4);
	pdog->run();
	pdog->fun();
	/*上面的更改后,狗变成了猫的特性*/
}

上述程序对应的内存图:


可以看出,一旦满足了多态的条件,程序自然按照上图的流程执行。

4、上面既然说了,虚函数表中存放的是函数的地址,那么能不能直接我们自己取出虚函数的地址,直接调用所需要的函数呢?

#include <iostream>
using namespace std;

class Animal{
public:
	virtual void run(int x){
		cout <<"run x="<<x<<endl;
	}
	virtual void fun(int x){
		cout <<"fun x="<<x<<endl;
	}
	void show(){
		cout <<"this is show()"<<endl;
	}
};


int main()
{
	/*去掉函数名就是函数指针的类型,指针简化操作*/
	typedef void (*MFUN)(Animal* a,int x);/*MFUN就是虚表中的函数指针类型*/

	typedef MFUN* VTABLE;//MFUN*就是虚表类型

	Animal animal;
	VTABLE vt = *((VTABLE*)&animal);
	/*虚函数表表现为函数指针数组*/
	vt[0](&animal,100);
	vt[1](&animal,123);
	return 0;
}

虚表中存放的就是虚函数的函数指针,可以理解为函数指针的数组,通过typedef将指针降级。


5,虚析构函数

virtual关键字只能修饰成员函数或者析构函数,其他的函数都不行。

当我们用new创建一个指向子类对象的父类指针时,例如Animal * animal = new Dog()时,其中Animal时父类,Dog是子类,并且delete animal时,其子类对象的析构函数不会被调用,只会调用父类的析构函数。所以就会遇到一个问题,如果子类对象有自己独立的堆内存时,这部分内存就无法释放。这时,我们只需要在父类的析构函数上用virtual修饰即可,子类析构函数就会被调用。

#include <iostream>
using namespace std;

class Animal{
public:
	Animal(){
		cout <<"Animal()"<<endl;
	}
	virtual ~Animal(){
		cout <<"~Animal()"<<endl;
	}
};
class Dog:public Animal{
public:
	Dog(){
		cout <<"Dog()"<<endl;
	}
	~Dog(){
		cout <<"~Dog()"<<endl;
	}
};
int main(){
	Animal * pa = new Dog();
	delete pa;
	/*子类析构函数的调用必然引发父类析构*/
}

虚析构函数的应用场景:

当父类中有虚函数时,应该吧父类的析构函数定义成虚析构函数。

子类和父类中都有自己的堆内存分配时。



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c++面向对象三大特征封装、继承和多态知识总结 的相关文章

  • 调用拷贝构造函数的几种情况(附面试题)

    1 深拷贝和浅拷贝 拷贝构造函数的使用 有时候需要自己定义拷贝构造函数 以避免浅拷贝问题 在什么情况下需要用户自己定义拷贝构造函数 一般情况下 当类中成员有指针变量 类中有动态内存分配时常常需要用户自己定义拷贝构造函数 在什么情况下系统会调
  • C语言pcre库的使用及验证IP地址的合法性

    PCRE是一个用C语言编写的正则表达式函数库 它十分易用 同时功能也很强大 性能超过了POSIX正则表达式库和一些经典的正则表达式库 在使用PCRE库时 首先肯定是需要安装pcre的 不过一般的系统都会有自带的PCRE库 不过如果想使用最新
  • Vc/MFC中自定义消息及其PostMessage触发使用

    http blog csdn net ztz0223 article details 2058402 http blog csdn net a8082649 article details 7733527 http bbs csdn net
  • C/C++中浮点数格式学习——以IEEE75432位单精度为例

    这是浮点数的通常表示形式 在IEEE754中 单精度浮点数有如下形式 32位单精度 单精度二进制小数 使用32个比特存储 1 8 23位长 S Exp Fraction 31 30至23偏正值 实际的指数大小 127 22至0位编号 从右边
  • 无法打开源文件<sys/time.h>,但是用time.h编译就会出错,缺少gettimeofday()

    因为sys time h是uinx系统下的库文件 而现在使用的平台是在windows 由于未指明程序运行的系统 导致找不到对应的头文件 需要重新实现gettimeofday 函数 define WIN32 include
  • 经典面试题之new和malloc的区别

    new和malloc的区别是C C 一道经典的面试题 我也遇到过几次 回答的都不是很好 今天特意整理了一下 0 属性 new delete是C 关键字 需要编译器支持 malloc free是库函数 需要头文件支持 1 参数 使用new操作
  • Lua和C++交互总结(很详细)

    出处 http blog csdn net shun fzll article details 39120965 一 lua堆栈 要理解lua和c 交互 首先要理解lua堆栈 简单来说 Lua和C c 语言通信的主要方法是一个无处不在的虚拟
  • 继承,重载函数,派生函数

    继承是类与类之间的关系 是一个很简单很直观的概念 与现实世界中的继承 例如儿子继承父亲财产 类似 继承 Inheritance 可以理解为一个类从另一个类获取成员变量和成员函数的过程 例如类B继承于类A 那么B就拥有A的成员变量和成员函数
  • Java学习13:面向对象-多态(Polymorphism)内存分析图解

    1 概述 多态是Java面向对象三大特征之一 多态 Polymorphism 顾名思义 即对象具有多种形态 具体而言 是编译时类型 运行时类型 编译时类型 由声明时的类型决定 一般是父类 运行时类型 由实际对应的对象类型决定 具体是哪个子类
  • lua和测试(一)

    lua做为一门高级语言 在游戏产业运用到机会越来越多了 测试掌握几门脚本语言也有一定的重要性 以下对于lua组合输入做出一些引导 测试需要掌握的关于返回数值 主要用到布尔类 前言的指引 lua的语法比较简单和清晰 学过c语言的可以很好的掌握
  • 模板的完全特例化和部分特例化

    介绍 完全特例化就是类型完全明确的版本 而部分特例化指的是 只知道是几个参数的函数而不知道参数的类型 或者是只知道是引用或者是指针类型 而不知道具体是char 还是 int 模板特例化实例1 template
  • 手把手教你如何写一个三子棋/N子棋的小游戏

    这里写目录标题 第一步 游戏进入界面 第二步 初始化棋盘 第三步 打印棋盘 第四步 玩家和电脑下棋 第五步 判断输赢 三子棋或者N子棋怎么写 让我们先来玩一把 再来看看怎么写 程序运行界面 1为玩游戏 2为清屏 0为退出游戏 我们选1 然后
  • C++学习笔记12:输入输出流实例整理(文本文件读写,二进制文件读写,一组数据的文件读写,随机访问文件实例

    这也太难记了555老阔疼 文件读写示例 include
  • Open3D(C++)实现建筑物点云立面和平面分割提取

    Open3D C 实现建筑物点云立面和平面分割提取 近年来 点云技术在城市规划 机器人地图构建等领域得到广泛应用 本篇文章将介绍如何利用Open3D C 库实现建筑物点云立面和平面分割提取 准备工作 首先需要编译安装Open3D库 本文使用
  • visual studio 一直显示正在准备解决方案

    首先重启电脑 无法解决的情况下执行以下步骤 Kill Visual Studio Open Visual Studio without loading a solution Disable AnkhSvn as Source Control
  • stat 函数解析

    stat 函数的简单使用 stat 函数是用来获取文件的各种属性的一个linux下的常用API函数 函数原型为int stat const char path struct stat buf stat定义如下 struct stat dev
  • 一个简单的参数帮助框架,c实现

    文章目录 具体实现如下 include
  • Java反序列化漏洞-CC1利用链分析

    文章目录 一 前置知识 1 反射 2 Commons Collections是什么 3 环境准备 二 分析利用链 1 Transform
  • C/C++编程中的算法实现技巧与案例分析

    C C 编程语言因其高效 灵活和底层的特性 被广大开发者用于实现各种复杂算法 本文将通过10个具体的算法案例 详细探讨C C 在算法实现中的技巧和应用 一 冒泡排序 Bubble Sort 冒泡排序 Bubble Sort 是一种简单的排序
  • C中的内存使用问题

    请帮忙 操作系统 Linux 其中 sleep 1000 中 此时 top 显示Linux任务 给我写了7 7 MEM使用 valgrind 未发现内存泄漏 我明白 写得正确 所有 malloc 结果都是 NULL 但是为什么这次 睡眠 我

随机推荐

  • Openharmony环境搭建

    鸿蒙系统开发环境搭建 前言 工具下载 开发环境 HUAWEI DevEco Device Tool 开发环境的准备 Windows开发环境准备 获取软件 vscode 安装 安装Python 安装Node js 安装hpm 安装DevEco
  • android中跨进程通讯的4种方式

    android中跨进程通讯的4种方式 转自 http www androidsdn com article show 137 由于android系统中应用程序之间不能共享内存 因此 在不同应用程序之间交互数据 跨进程通讯 就稍微麻烦一些 在
  • 神经网络:LSTM基础学习

    1 LSTM简介 在时间序列数据学习中 传统的循环神经网络 RNN 存在较多的学习瓶颈和技术缺陷 而长短时记忆 LSTM 神经网络克服了循环神经网络的缺陷 使其在长时间序列数据学习训练中能克服梯度爆炸和梯度消失的瓶颈 展现出超强的长系列数据
  • 比例数据可视化——(pyecharts)

    本文数据来自于大数据可视化技术这本书 用于复习 1 饼图 1 1 基础饼图 import pandas as pd from pyecharts charts import Pie from pyecharts import options
  • 推荐前 6 名 JavaScript 和 HTML5 游戏引擎

    推荐 使用 NSDT场景编辑器 助你快速搭建3D应用场景 事实是 自从引入JavaScript WebGL API以来 现代浏览器具有直观的功能 使它们能够渲染更复杂和复杂的2D和3D图形 而无需依赖第三方插件 你可以用纯粹的JavaScr
  • springboot+mybatisplus 配置多数据源打印sql语句失效的问题

    目录 1 如果没有配置多数据源 下打印sql 只在yml里面配置就会报如下的信息 2 这里说一下解决方法两种方式 都是在多数据源配置文件下 加入代码解决 1 如果没有配置多数据源 下打印sql 只在yml里面配置就会报如下的信息 Creat
  • windows 环境下,浏览器如何拉起应用程序?

    由于浏览器的限制 我们无法在web程序中直接拉起应用程序 今天告诉大家一个方式 可以在一定程度上处理这个问题 首先用java程序生成一个注册表文件 package com fh controller system regedit impor
  • 初识IDA工具

    工具 IDA工具 链接 https pan baidu com s 1Zgzpws6l2M5j1wkCZHrffw 提取码 ruyu 里面有安装密码 PassWord qY2jts9hEJGy 里面分析32位和64位启动快捷方式 打开IDA
  • 十、C++11左值右值、左值引用、右值引用、万能引用、完美转发

    10 C 11左值右值 左值引用 右值引用 10 1 左值 右值 左值 可以在 左边使用的值 右值 只能在 右边使用的值 字面量 中间结果 临时对象 匿名对象 无法直接取地址 不能使用左值引用 10 2 左值引用 右值引用 实例 左值引用
  • day35 贪心

    860 柠檬水找零 按照客户给的钱进行不同的找钱策略 406 根据身高重建队列 先按照身高进行高到低排序 再按照位次插入即可 452 用最少数量的箭引爆气球 先按照左边界进行排序 判断是否重叠 如果重叠了直接count 如果不重叠更新最小的
  • cargo 中 github 换源

    touch cargo config echo source crates io replace with tuna source tuna registry https mirrors tuna tsinghua edu cn git c
  • CTF安全竞赛介绍

    目录 一 赛事简介 二 CTF方向简介 1 Web Web安全 1 简介 2 涉及主要知识 2 MISC 安全杂项 1 介绍 2 涉及主要知识 3 Crypto 密码学 1 介绍 2 涉及主要知识 4 Reverse 逆向工程 1 介绍 2
  • 封装element-ui中的Drawer(抽屉)

    之前我都不知道有drawer这个方法 平常对于那些弹框我一般习惯用dialog这个组件 然而前几天 我发现 drawer也用起来不错 便想起来 把他封装起来 好复用 下面呢 就直接上代码了
  • linux三个线程输出abc,三个线程循环输出ABC10次

    import java util concurrent locks Lock import java util concurrent locks ReentrantLock public class ABC private static i
  • Java集合中用Collections排序

    Collections简介及常用功能 java util Collections是集合工具类 用来对集合进行操作 部分主要方法如下 public static void reverse List
  • 记录工作中使用easyExcel实现复杂一对多excel表格导出及多sheet页导出

    业务场景 一个工单对应多个项目 一个项目对应多个配件信息 这样形成了三层级联的一对多的业务场景 实现效果如下 功能实现 1 引入maven
  • Visio打开或取消箭头的自动吸附和自动连接

    在用Visio画图时Visio的自动对齐 自动连接 自动吸附功能确实能带了很多便利 但在画连接线时 Visio总是自动连接箭头与图形的固定节点 想要微调一下连接位置 就显得很不方便 需要关闭自动连接功能 这些小设置 用时总是不记得 特记在这
  • 华为Mate60 Pro曝光:麒麟芯片9100 or 骁龙8Gen2+5G,7699元起,你觉得如何?

    最近网上关于华为Mate60系列的爆料逐渐增多 尤其是对于新机到底支不支持5G 众说纷纭 而且老是变动 7月14日 有数码博主爆料称 华为Mate60系列确实分前期和后期版本 前期为了秀肌肉 会展示新的成果 据可靠消息源分享 确实有分前期与
  • matlab单个像素面积,我用MATLAB计算出了图像目标区域的像素点个数,请问知道了目标区域的像素点怎么计算目标区域的面积?...

    满意答案 下面是一个简单的计算轮廓包含起来的像素点的个数的程序 step 1 clear all clc I imread test bmp 读入图片 bwI im2bw I 0 5 转化为二值图像 L bwlabel bwI 4 将四连通
  • c++面向对象三大特征封装、继承和多态知识总结

    面向对象三大特征 封装 继承 多态 一 封装 该公开的就公开话 该私有的就隐藏掉 主要是由public private实现 作用是便于分工和分模块 防止不必要的扩展 二 继承 就是一种传承 可以把父类型中的数据传承到子类中 子类除了传承了父