C++面向对象编程(类和对象)

全部学完提供一个练习的项目,在博主的主页可以找到该免费资源


文章目录

  • 一、封装
    • 示例1:
    • 访问权限
    • struct 和 class 区别
    • 检测数据有效性:
    • 练习1:
    • 练习2:
    • 构造函数
    • 析构函数
    • 构造函数的调用和分类
    • 拷贝构造函数调用时机
    • 初始化列表
    • 类对象作为类对象
    • 静态成员
    • 静态成员函数
    • C++对象模型和this指针
    • this指针
    • 空指针访问成员函数
    • const修饰成员函数
    • 友元
    • 运算符重载
    • 1.加号运算符重载
    • 2.全局函数重载+号
    • 3.重载左移运算符,前置++运算符和后置++运算符
    • 4.赋值运算符= 重载
    • 5.关系运算符重载,将两个自定义对象进行比对
    • 重载()
  • 二、继承
    • 继承方式:
    • 继承中的对象模型
    • 继承中的析构和构造顺序
    • 继承中同名成员处理方式
    • 继承同名静态成员处理方式
    • 菱形继承
  • 三、多态
    • 动态多态满足条件
    • 动态多态使用
    • 案例
    • 纯虚函数和抽象类
    • 虚析构和纯虚析构
    • 虚析构
    • 纯虚析构
    • 案例


C++面向对象三大特性: 封装,继承,多态


一、封装

意义:将属性和行为加以权限控制

语法: class类名{访问权限: 属性/行为};

示例1:

#include <iostream>
using namespace std;//圆周率
const double PI=3.14;//class代表一个类,后面紧跟类名
class Circle 
{//访问权限//公共权限
public://属性	//半径int m_r;//行为//获取圆的周长double calculateZC(){return 2*PI*m_r;}
};int main()
{//通过圆类 创建具体的圆(对象)//实例化(通过一个类创建一个对象的过程)Circle c1;//给圆对象属性进行赋值c1.m_r=10;cout<<"圆的周长为:"<<c1.calculateZC()<<endl;system("pause");return 0;
}

访问权限

有三种:
1.public 公共权限
2.protected 保护权限
3.private 私有权限

#include <iostream>
#include <string>
using namespace std;//访问权限 
//三种
//公共权限 public     成员 类内可以访问 类外可以访问
//私有权限 protected  成员 类内可以访问 类外不可以访问
//保护权限 private    成员 类内可以访问 类外不可以访问class Person 
{
public://公共权限string m_Name;protected://保护权限string m_Car;private://私有权限int m_Password;private:void func(){m_Name="小黄";m_Car="托马斯小火车";m_Password=031116;}
};int main()
{//实例化对象Person p1;p1.m_Name="马斯特";
//	p1.m_Car="特斯拉"; 保护权限的内容在类外无法访问
//	p1.m_Password=000000; 私有权限的内容在类外无法访问
//  p1.func;system("pause");return 0;
}

struct 和 class 区别

默认访问权限不同

struct 默认权限为公共
class 默认权限为私有

#include <iostream>
using namespace std;class C1
{int m_A; //默认权限 私有	
};struct C2
{int m_A;	//默认权限 私有
};int main()
{C1 c1;//c1.m_A=100;C2 c2;c2.m_A=100;system("pause");return 0;
}

将成员属性设置为私有,可以自己控制读写权限,便于检测数据的有效性

#include <iostream>
#include <string>
using namespace std;//成员属性设置为私有
class Person
{
public:void setName(string name){m_Name=name;}string getName(){return m_Name;}int getAge(){m_Age=0;	//初始化return m_Age;}void setLover(string lover){m_Lover=lover;}private:	//class中private可以省略string m_Name;	//可读可写int m_Age;	//只读string m_Lover;	//只写};int main()
{Person p;p.setName("红色风暴");cout<<"姓名为:"<<p.getName()<<endl;cout<<"英雄可以受侮辱,但你不可以踩我的黄金切尔西"<<endl;cout<<"年龄为:"<<p.getAge()<<endl;//p.Age=18;//p.setAge=18; 只读不可写p.setLover("霉你不行");
//	cout<<"情人:"<<p.m_Lover<<endl;
//	cout<<"情人:"<<p.getLover<<endl;	只写权限system("pause");return 0;
}

定义属性为private,若想可读可写则定义public权限的set和get函数

检测数据有效性:

#include <iostream>
#include <string>
using namespace std;//成员属性设置为私有
class Person
{
public:void setName(string name){m_Name=name;}string getName(){return m_Name;}//可读可写 如果想修改(年龄的范围必须是0~150)int getAge(){m_Age=0;	//初始化return m_Age;}void setAge(int age){if(age<0||age>150){m_Age=0;cout<<"小伙子你很优秀啊"<<endl;return;}m_Age=age;}void setLover(string lover){m_Lover=lover;}private:	//class中private可以省略string m_Name;	//可读可写int m_Age;	//只读string m_Lover;	//只写};int main()
{Person p;p.setName("红色风暴");cout<<"姓名为:"<<p.getName()<<endl;cout<<"英雄可以受侮辱,但你不可以踩我的黄金切尔西"<<endl;p.setAge(1000);cout<<"年龄为:"<<p.getAge()<<endl;//p.Age=18;//p.setAge=18; 只读不可写p.setLover("霉你不行");
//	cout<<"情人:"<<p.m_Lover<<endl;
//	cout<<"情人:"<<p.getLover<<endl;	只写权限system("pause");return 0;
}

练习1:

#include <iostream>
#include <string>
using namespace std;//分别利用全局函数和成员函数判断立方体是否相等
class Cube
{
public://行为//设置长宽高void setZ(int l, int w, int h){m_L = l;m_W = w;m_H = h;}//获取长宽高int getL(){return m_L;}int getW(){return m_W;}int getH(){return m_H;}//获取立方体面积int cS(){return 2 * m_L * m_W + 2 * m_L * m_H + 2 * m_W * m_H;}//获取立方体体积int cV(){return m_H * m_L * m_W;}//利用成员函数判断两个立方体是否相等bool isSameByClass(Cube &c){if (m_L == c.getL() && m_H == c.getH() && m_W == c.getW()){return true;}return false;}private://属性int m_L;	//长int m_W;	//宽int m_H;	//高
};//利用全局函数判断两个立方体是否相等
bool isSame(Cube c1, Cube c2)
{if (c1.getH() == c2.getH() && c1.getL() == c2.getL() && c1.getW() == c2.getW()){return true;}return false;
}int main()
{//创建立方体对象Cube c1;c1.setZ(10, 10, 10);cout << "c1的面积:" << c1.cS() << endl;cout << "c1的体积:" << c1.cV() << endl;Cube c2;c2.setZ(10, 10, 10);bool ref = isSame(c1, c2);if (ref) {//TODOcout << "相等" << endl;}else {//TODOcout << "不相等" << endl;}ref = c1.isSameByClass(c2);if (ref) {//TODOcout << "相等" << endl;}else {//TODOcout << "不相等" << endl;}system("pause");return 0;
}

练习2:

#include <iostream>
using namespace std;class Point
{
public:void setX(int x){m_X = x;}int getX(){return m_X;}void setY(int y){m_Y = y;}int getY(){return m_Y;}private:int m_X;int m_Y;
};class Circle
{
public:void setR(int r){m_R = r;}int getR(){return m_R;}void setC(Point c){m_Center = c;}Point getC(){return m_Center;}private:int m_R;Point m_Center;
};//判断点和圆关系
void isInCircle(Circle & c, Point & p)
{int d=(c.getC().getX() - p.getX())* (c.getC().getX() - p.getX()) + (c.getC().getY() - p.getY()) * (c.getC().getY() - p.getY());int rD = c.getR()*c.getR();if (d == rD){cout << "点在圆上" << endl;}else if (d > rD){cout << "点在圆外" << endl;}else{cout << "点在圆内" << endl;}
}int main()
{//创建圆Circle c;c.setR(10);Point Center;Center.setX(10);Center.setY(0);c.setC(Center);//创建点Point p;p.setX(10);p.setY(10);//判断关系isInCircle(c, p);system("pause");return 0;
}

构造函数

语法:类名(){}
1.没有返回值也不写void
2.函数名称与类名相同
3.可以有参数,因此可以发生重载
4.程序在调用对象时会自动调用构造,无须手动调用,且只会调用一次

析构函数

语法:~类名(){}
1.没有返回值也不写void
2.函数名称与类名相同,在名称前加上符号
3.不可以有参数,因此不能重载
4.程序在对象销毁钱会自动调用析构,无须手动调用,而且只会调用一次

#include <iostream>
using namespace std;//对象的初始化和清理
class Person
{
public://1.构造函数Person()//若未写,编译器会自动构造{cout << "构造函数的调用" << endl;}//对象在销毁前会自动调用析构函数,而且只会调用一次//2.析构函数 进行清理的操作~Person(){cout << "Person的析构函数的调用" << endl;}
};void test01()
{Person p; //栈上
}int main()
{test01();system("pause");return 0;
}

构造和析构都是必须有的实现,如果我们自己不提供,编译器会提供一个空是心啊的构造和析构

构造函数的调用和分类

1.按参数分类:有参构造和无参构造
2.按类型分类:普通构造和拷贝构造

三种调用方式:
括号法
显示法
隐式转换法

#include <iostream>
using namespace std;class Person
{
public://非拷贝构造的均为普通构造//无参构造Person()//默认情况提供无参构造{cout << "Person的无参构造函数调用" << endl;}//有参构造Person(int a){age = a;cout << "Person的有参构造函数调用" << endl;}//拷贝构造Person(const Person &p){//将传入的人身上的所有属性,拷贝到自己身上age = p.age;cout << "拷贝构造函数!" << endl;}//析构函数,作用为释放~Person(){cout << "Person的析构函数调用" << endl;}public:int age;
};//构造函数的调用
//调用无参构造函数
void test01()
{Person p(10);
}//调用有参构造函数
void test02()
{//1.括号法Person p1; //默认构造函数调用Person p2(10); //有参构造函数调用Person p3(p2); //拷贝构造函数调用cout << "p2的年龄:" << p2.age <<endl;cout << "p2的年龄:" << p3.age <<endl;//2.显式法Person p4;Person p5 = Person(10);Person p6 = Person(p5);Person(10);	//匿名对象 特点:当前行执行结束后,系统会立即回收匿名对象cout << "aaaa" << endl;//不要利用拷贝构造函数 初始化匿名对象//编译器会认为 Person(p_6)===Person p_6Person(p_6);//3.隐式转换法Person p7 = 10; //相当于写了 Perosn p4 = Person(10);Person p8 = p7;	//Person p5 = Person (p4);}int main()
{test01();test02();system("pause");return 0;
}

编译结构如下:
在这里插入图片描述

拷贝构造函数调用时机

1.使用一个已经创建完毕的对象来初始化一个新对象
2.值传递的方式给函数参数传值
3.以值方式返回局部对象

#include <iostream>
using namespace std;//拷贝构造函数使用时机class Person
{
public:Person(){cout << "Person默认函数调用" << endl;}Person(int age){m_Age = age;cout << "有参构造函数调用" << endl;}Person(const Person& p){m_Age = p.m_Age;cout << "拷贝构造函数调用" << endl;}~Person(){cout << "Person析构函数调用" << endl;}int m_Age;
};//1.使用一个已经创建完毕的对象来初始化一个新对象
void test01()
{Person p1(20);Person p2(p1);	//调用拷贝构造函数cout << "p2的年龄:" << p2.m_Age << endl;
}//2.值传递的方式给函数参数传值
void doWork(Person p)
{}void test02()
{Person p;doWork(p);
}//3.值方式返回局部对象
Person doWork2()
{Person p3;return p3;
}void test03()
{Person p4 = doWork2();
}int main()
{test01();cout << endl;test02();cout << endl;test03();system("pause");return 0;
}

初始化列表

作用:
C++提供了初始化列表语法,用来初始化属性

语法:构造函数():属性1(值1),属性2(值2)…()

#include <iostream>
using namespace std;//初始化列表
class Person
{
public://初始化列表初始化属性Person() : m_A(30), m_B(20), m_C(10){}int m_A;int m_B;int m_C;
};void test01()
{Person p;cout << "m_A=" << p.m_A << endl;cout << "m_B=" << p.m_B << endl;cout << "m_C=" << p.m_C << endl;
}int main()
{test01();system("pause");return 0;
}

当在外需要赋初值时改为:

#include <iostream>
using namespace std;//初始化列表
class Person
{
public://初始化列表初始化属性Person(int a,int b,int c) : m_A(a), m_B(b), m_C(c){}int m_A;int m_B;int m_C;
};void test01()
{Person p(30,20,10);cout << "m_A=" << p.m_A << endl;cout << "m_B=" << p.m_B << endl;cout << "m_C=" << p.m_C << endl;
}int main()
{test01();system("pause");return 0;
}

类对象作为类对象

C++类中的对象可以是另一个类的对象,我们称成员为对象成员

例如:

class A{}
class B
{A a;
}

B类中有对象A作为成员,A为对象成员

当其他类对象作为本类成员
构造时先构造类对象,再构造自身
析构顺序和构造相反

#include <iostream>
#include <string>
using namespace std;class Phone
{
public:Phone(string pName){m_pName = pName;}~Phone(){cout << "Phone的析构函数调用" << endl;}string m_pName;
};//类对象作为类成员
class Person
{
public:Person(string name, string pName):m_Name(name),m_Phone(pName){}string m_Name;Phone m_Phone;~Person(){cout << "Person的析构函数调用" << endl;}
};void test01()
{Person p("李华", "垃圾苹果");cout << p.m_Name << "拿着" << p.m_Phone.m_pName << endl;
}int main()
{test01();system("pause");return 0;
}

静态成员

静态成员就是在成员变量和成员函数前加上关键字static,称为静态成员

静态成员分为:

静态成员变量

1.所有对象共享同一份数据
2.在编译阶段分配内存
2.类内声明,类外初始化

#include <iostream>
using namespace std;//静态成员变量
class Person
{
public ://所有对象都共享同一份数据//编译阶段就分配内存//类内声明,类外初始化static int m_A;//静态成员变量也有访问权限
private:static int m_B;
};//类外初始化
int Person :: m_A = 100;
int Person :: m_B = 200;void test01()
{	Person p1;cout << p1.m_A << endl;Person p2;p2.m_A = 200;cout << p2.m_A << endl;
}void test02()
{//静态成员变量 不属于某个对象 所有对象都共享同一份数据//因此静态成员变量有两种访问方式//1.通过对象进行访问Person p3;cout << p3.m_A << endl;//2.通过类名进行访问cout << Person::m_A << endl;//cout << Person::m_B << endl;
}int main()
{test01();test02();system("pause");return 0;
}

静态成员函数

1.所有对象共享同一个函数
2.静态成员函数只能访问静态成员变量

#include <iostream>
using namespace std;//静态成员函数
//所有对象共享同一个函数
//静态成员函数只能访问静态成员变量class Person
{
public:static void func(){m_A = 100;	//静态成员函数可以访问静态成员变量//m_B = 200;	静态成员函数不可以访问非静态成员变量cout << "static void func调用" << endl;}static int m_A;	//静态成员变量int m_B;	//非精要成员变量//静态成员函数也有访问权限
private:static void func2(){cout << "static void func2调用"<<endl;}
};int Person::m_A = 0;void test01()
{//1.通过对象访问Person p;p.func();//2.通过类名访问Person::func();//Person::func2(); 类外访问不到私有静态成员函数
}int main()
{test01();system("pause");return 0;
}

C++对象模型和this指针

成员变量和成员函数分开存储

C++中,类内的成员变量和成员函数分开存储

只有非静态成员变量才属于类的对象上

#include <iostream>
using namespace std;//成员变量和成员函数是分开存储的
class Person
{int m_A;	//非静态成员变量static int m_B;	//静态成员变量 不属于类对象上void func() {}//非静态成员函数 不属于类对象上static void func2() {}	//静态成员函数 不属于类对象上
};int Person::m_B=0;void test01()
{Person p;//空对象占用内存空间为:1//每个空对象也应该有一个独一无二的内存地址cout << "size of p=" << sizeof(p) << endl;
}int main()
{test01();system("pause");return 0;
}

this指针

this指针指向被调用的成员函数所属的对象

this指针是隐含每一个非静态成员函数内的一种指针

this指针不需要定义,直接使用即可

#include <iostream>
using namespace std;class Person
{
public:Person(int age){//this指针指向被调用的成员函数所属的对象this->age = age;}int age;
};//1.解决名称冲突
void test01()
{Person p1(19);cout << "p1的年龄是:" << p1.age << endl;
}int main()
{test01();system("pause");return 0;
}
#include <iostream>
using namespace std;class Person
{
public:Person(int age){this->age = age;}Person PersonAddAge(Person &p){this -> age += p.age;//this指向p2的指针,而*this指向的就是p2对象本体return *this;}int age;
};//1.解决名称冲突
void test01()
{Person p1(19);cout << "p1的年龄是:" << p1.age << endl;
}//返回对象本身用 *this
void test02()
{Person p1(10);Person p2(p1);p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1);cout << "p2的年龄为:" << p2.age << endl;
}int main()
{test01();test02();system("pause");return 0;
}

空指针访问成员函数

C++空指针也可以调用成员函数,但是要注意有没有用到this指针

如果用到this指针,需要加以判断保证代码的健壮性

#include <iostream>
using namespace std;//空指针调用成员函数
class Person
{
public:void showClassName(){cout << "this is Person class" << endl;}void showPersonAge(){if (this == NULL){return;}//报错原因:传入指针为NULLcout << "age=" << this -> m_Age << endl;}int m_Age;
};void test01()
{Person* p = NULL;p->showClassName();
//	p->showPersonAge();
}int main()
{system("pause");return 0;
}

const修饰成员函数

常函数:

成员函数后加const后我们称这个函数为常函数

常函数内不可以修改成员属性

成员属性声明时加关键字mutable后,在常函数中依然可以修改

常对象:

声明对象前加const称该对象为常对象

常对象只能调用常函数

#include <iostream>
using namespace std;//常函数
class Person
{
public ://this指针的本质 指针常量 指针的指向时不可以修改的//const Person * const this;//在成员函数后面加上const,修饰的是this指向,让指针指向的值也不可以修改void showPerson() const{//	m_A = 100;//  this指针不可以修改指针的指向//	this=NULL;}void func();int m_A;mutable int m_B;	//特殊变量,即使在常函数中,也可以修改这个值//加关键字mutable
};//常对象
void test02()
{const Person p;	//在对象前加const,变为常对象//p.m_A = 100;p.m_B = 1000;	//m_B是特殊值,在常对象下也可以修改//常对象只能调用常函数p.showPerson();//p.func();
}void test01()
{Person p;p.showPerson();
}int main()
{test01();system("pause");return 0;
}

友元

友元的目的: 让一个函数或者类访问另一个类中私有成员

友元关键字: friend

友元的三种实现:
1.全局函数做友元
2.类做友元
3.成员函数做友元

全局函数做友元示例

#include <iostream>
#include <string>
using namespace std;//建筑物类
class Building
{//全局函数是友元,可以访问私有成员friend void goodGay(Building* building);public:Building(){m_SittingRoom = "客厅";m_BedRoom = "卧室";}string m_SittingRoom;private:string m_BedRoom;
};//全局函数
void goodGay(Building *building)
{cout << "好基友全局函数 正在访问:" << building->m_SittingRoom << endl;cout << "好基友全局函数 正在访问:" << building->m_BedRoom << endl;
}void test01()
{Building building;goodGay(&building);
}int main()
{test01();system("pause");return 0;
}

类做友元示例

#include <iostream>
#include <string>
using namespace std;//类做友元
class Building;class GoodGay
{
public :GoodGay();void visit();	//参观函数 访问Building中的属性Building * building;
};class Building
{friend class GoodGay;
public :Building();string m_SittingRoom;private :string m_BedRoom;
};//类外写成员函数
Building::Building()
{m_SittingRoom = "客厅";m_BedRoom = "卧室";
}GoodGay::GoodGay()
{//创建建筑物对象building = new Building;	//在堆区创建对象
}void GoodGay::visit()
{cout << "好基友类正在访问:" << building->m_SittingRoom << endl;cout << "好基友类正在访问:" << building->m_BedRoom << endl;
}void test01()
{GoodGay gg;gg.visit();
}int main()
{test01();system("pause");return 0;
}

成员函数做友元

#include <iostream>
#include <string>
using namespace std;class Building;class GoodGay 
{
public:GoodGay();void visit1();	//让visit1函数可以访问Building中的私有成员void visit2();	//让visit2函数不可以访问Building中的私有成员Building * building;
};class Building
{//告诉编译器 GoodGay类下的visit函数成员函数作为本类的好朋友,可以访问自由成员friend void GoodGay::visit1();public:Building();string m_SittingRoom;private:string m_BedRoom;
};//类外实现成员函数
Building::Building()
{m_SittingRoom = "客厅";m_BedRoom = "卧室";
}GoodGay::GoodGay()
{building = new Building;}void GoodGay::visit1()
{cout << "visit1函数正在访问" << building->m_SittingRoom << endl;cout << "visit1函数正在访问" << building->m_BedRoom << endl;
}
void GoodGay::visit2()
{cout << "visit2函数正在访问" << building->m_SittingRoom << endl;//  cout << "visit2函数正在访问" << building->m_BedRoom << endl;
}void test01()
{GoodGay gg;gg.visit1();gg.visit2();
}int main()
{test01();system("pause");return 0;
}

运算符重载

运算重载概念:

对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型

1.加号运算符重载

#include <iostream>
using namespace std;//加号运算符重载class Person
{
public ://1.成员函数重载+号Person operator+ (Person& p){Person temp;temp.m_A = this->m_A + p.m_A;temp.m_B = this->m_B + p.m_B;return temp;}int m_A;int m_B;
};void test01()
{Person p1;p1.m_A = 10;p1.m_B = 10;Person p2;p2.m_A = 20;p2.m_B = 20;Person p3=p1+p2;cout << "p3.m_A=" << p3.m_A << endl;cout << "p3.m_B=" << p3.m_B << endl;
}int main()
{test01();system("pause");return 0;
}

2.全局函数重载+号

#include <iostream>
using namespace std;//加号运算符重载
class Person
{
public :int m_A;int m_B;
};//全局函数重载+号
Person operator+(Person &p1, Person &p2)
{Person temp;temp.m_A = p1.m_A + p2.m_B;temp.m_B = p1.m_A + p2.m_B;return temp;
}void test01()
{Person p1;p1.m_A = 10;p1.m_B = 10;Person p2;p2.m_A = 20;p2.m_B = 20;Person p3=p1+p2;cout << "p3.m_A=" << p3.m_A << endl;cout << "p3.m_B=" << p3.m_B << endl;
}int main()
{test01();system("pause");return 0;
}

3.重载左移运算符,前置++运算符和后置++运算符

#include <iostream>
using namespace std;//重载递增运算符//自定义整型
class MyInteger
{friend ostream& operator <<(ostream& cout, MyInteger);public:MyInteger(){m_Num = 0;}//重载前置++运算符//返回引用是为了一直对一个数据进行操作MyInteger & operator++(){//先进性++运算m_Num++;//再将自身返回return *this;}//重载后置++运算符MyInteger operator ++(int)	//int代表占位参数,可以用于区别前置和后置递增{//先 记录当时结果MyInteger temp = *this;//后 递增m_Num++;//最后将记录结果做返回return temp;}private:int m_Num;
};//重载左移运算符
ostream & operator <<(ostream & cout, MyInteger myint)
{cout << myint.m_Num;return cout;
}void test01()
{MyInteger myint;cout << myint << endl;cout << ++(++myint) << endl;cout << myint << endl;
}void test02()
{MyInteger myint;cout << myint << endl;cout << myint++ << endl;cout << myint << endl;
}int main()
{test01();cout << endl;test02();system("pause");return 0;
}

4.赋值运算符= 重载

#include <iostream>
using namespace std;//赋值运算符重载class Person
{
public:Person(int age){m_Age=new int(age);}~Person(){if (m_Age != NULL){}}//重载 赋值运算符Person& operator=(Person & p){//编译器提供浅拷贝//m_Age = p.m_Age;//应该判断是否有属性在堆区,如果有,先释放干净再深拷贝if (m_Age != NULL){delete m_Age;m_Age = NULL;}//深拷贝m_Age = new int(*p.m_Age);//返回对象本身return *this;}int * m_Age;
};void test01()
{Person p1(18);Person p2(20);Person p3(24);p3 = p2 = p1;	//赋值操作cout << "p1的年龄:" << *p1.m_Age << endl;cout << "p2的年龄:" << *p2.m_Age << endl;cout << "p3的年龄:" << *p3.m_Age << endl;
}int main()
{test01();system("pause");return 0;
}

5.关系运算符重载,将两个自定义对象进行比对

#include <iostream>
#include <string>
using namespace std;//重载关系运算符
class Person
{
public:Person(string name,int age){m_Name = name;m_Age = age;}//重载==bool operator==(Person &p){if (this->m_Name == p.m_Name && this->m_Age == p.m_Age){return true;}return false;}//重载!=bool operator!=(Person& p){if (this->m_Name == p.m_Name || this->m_Age == p.m_Age){return false;}return true;}string m_Name;int m_Age;
};void test01()
{Person p1("Tom", 18);Person p2("Jerry", 3);if (p1 == p2){cout << "p1和p2相等" << endl;}else{cout << "p1和p2不相等" << endl;}
}int main()
{test01();system("pause");return 0;
}

重载()

又称仿函数,没有固定写法,非常灵活

#include <iostream>
#include <string>
using namespace std;//函数调用运算符重载//打印输出类
class MyPrint
{
public://重载函数调用运算符void operator ()(string test){cout << test << endl;}};void test02(string test)
{cout << test << endl;
}void test01()
{MyPrint myprint;myprint("hello world");	//由于使用起来非常类似于函数调用,因此被称为仿函数test02("hello world");
}int main()
{test01();system("pause");return 0;
}

没有固定写法

#include <iostream>
#include <string>
using namespace std;//函数调用运算符重载//自加类
class MyAdd
{
public:int operator ()(int num1, int num2){return num1 + num2;}
};void test01()
{MyAdd myadd;int res=myadd(100, 200);cout << "res= " << res << endl;//匿名函数对象cout << MyAdd()(100, 100) << endl;
}int main()
{test01();system("pause");return 0;
}

二、继承

继承的好处:减少重复代码
语法:class 子类:继承方式:父类

子类也称为派生类
父类也称为基类

继承方式:

1.公共继承
2.保护继承
3.私有继承

公共继承示例

//公共继承
class Base1
{
public:int m_A;
protected:int m_B;
private:int m_C;
};class Son1 : public Base1
{
public:void func(){m_A = 10;	//父类中的公共权限成员到子类中依然是公共权限m_B = 10;	//父类中的保护权限成员到子类中依然是保护权限//m_C = 10;	//父类中的私有权限成员 子类访问不到}
};void test01()
{Son1 s1;s1.m_A = 100;//s1.m_B = 100;	保护权限类外访问不到
}

保护继承示例:

//保护继承
class Base2
{
public:int m_A;
protected:int m_B;
private:int m_C;
};class Son2 :protected Base2
{
public:void func(){m_A = 100;	//父类公共成员 到子类中变为保护权限m_B = 100;	//父类保护成员 到子类中权限不变//	m_C = 100;	父类私有成员 子类访问不到}
};void test02()
{Son2 s2;//s2.m_A = 1000;	在Son2中m_A变为保护权限,因此类外访问不到
}

私有继承示例

//私有继承
class Base3
{
public:int m_A;
protected:int m_B;
private:int m_C;
};class Son3 : private Base3
{
public:void func(){m_A = 100;	//父类中公共成员到子类中变为私有成员m_B = 100;	//父类中保护成员到子类中变为私有成员//	m_C = 100 父类中私有成员子类访问不到}
};void test03()
{Son3 s3;//s3.m_A = 1000;	到Son3中变为私有成员,类外访问不到
}class Grandson3 : public Son3
{
public:void func(){//	m_A = 1000;	到了Son3中m_A变为私有成员,其子类也访问不到}
};

继承中的对象模型

#include <iostream>
#include <string>
using namespace std;//继承中的对象模型class Base
{
public:int m_A;
protected:int m_B;
private:int m_C;
};class Son : public Base
{
public:int m_D;
};void test01()
{cout << "size of Son=" << sizeof(Son) << endl;//16//父类中所有非静态成员属性都会被子类继承下去//父类中私有成员属性被百年一起隐藏,访问不到,但确实被继承
}int main()
{test01();system("pause");return 0;
}

继承中的析构和构造顺序

子类继承父类后,当创建子类对象,也会调用父类的构造函数

#include <iostream>
#include <string>
using namespace std;//继承中的构造和析构顺序
class Base
{
public:Base(){cout << "Base的构造函数!" << endl;}~Base(){cout << "Base的析构函数!" << endl;}
};class Son :public Base
{
public:Son(){cout << "Son的构造函数!" << endl;}~Son(){cout << "Son的析构函数!" << endl;}
};void test01()
{//先构造父类再构造子类,析构的顺序与构造的顺序相反Son s;
}int main()
{test01();system("pause");return 0;
}

继承中同名成员处理方式

访问 子类同名成员 直接访问即可
访问 父类同名成员 需要加作用域

#include <iostream>
#include <string>
using namespace std;//继承中同名成员处理
class Base
{
public:Base(){m_A = 100;}void func(){cout << "Base-func()调用" << endl;}int m_A;
};class Son :public Base
{
public:Son(){m_A = 200;}void func(){cout << "Son-func()调用" << endl;}int m_A;
};//同名属性处理
void test01()
{Son s1;cout << "Son下m_A=" << s1.m_A << endl;cout << "Base下m_A=" << s1.Base::m_A << endl;	//需要加作用域
}//同名成员函数处理
void test02()
{Son s2;s2.func();	//直接调用调用的是子类中的同名成员函数s2.Base::func();
}int main()
{test01();test02();system("pause");return 0;
}

如果子类中出现和父类同名的成员函数

#include <iostream>
#include <string>
using namespace std;//继承中同名成员处理
class Base
{
public:Base(){m_A = 100;}void func(){cout << "Base-func()调用" << endl;}void func(int a){cout << "Base-func(int a)调用" << endl;}int m_A;
};class Son :public Base
{
public:Son(){m_A = 200;}void func(){cout << "Son-func()调用" << endl;}int m_A;
};//同名属性处理
void test01()
{Son s1;cout << "Son下m_A=" << s1.m_A << endl;cout << "Base下m_A=" << s1.Base::m_A << endl;	//需要加作用域
}//同名成员函数处理
void test02()
{Son s2;s2.func();	//直接调用调用的是子类中的同名成员函数s2.Base::func();//如果子类中出现和父类同名的成员函数//子类的同名成员会隐藏掉父类中所有同名成员函数//如果想访问需要加作用域s2.Base::func(100);
}int main()
{test01();test02();system("pause");return 0;
}

继承同名静态成员处理方式

静态成员和非静态成员出现同名,处理方式一致

#include <iostream>
#include <string>
using namespace std;//继承同名静态成员处理方式
//同名静态属性
class Base
{public:static int m_A;	//静态成员变量类内声明,类外初始化static void func(){cout << "Base-static void func()" << endl;}static void func(int a){cout << "Base-static void func(int a)" << endl;}
};
int Base::m_A = 100;	class Son :public Base
{
public:static int m_A;static void func(){cout << "Son-static void func()" << endl;}
};
int Son::m_A = 200;	//静态成员变量类内声明,类外初始化//访问静态属性有两种
void test01()
{//1.通过对象访问cout << "通过对象访问:" << endl;Son s;cout << "Son 下m_A=" << s.m_A << endl;cout << "Base 下m_A=" << s.Base::m_A << endl;//2.通过类名访问cout << "通过类名访问" << endl;cout << "Son下m_A=" << Son::m_A << endl;cout << "1.Base下m_A=" << Base::m_A << endl;//直接通过父类作用域访问cout << "2.Base下m_A=" << Son::Base::m_A << endl;	//通过子类访问父类
}void test02()
{//1.通过对象访问cout << "通过对象访问" << endl;Son s;s.func();s.Base::func();//2.通过类名访问cout << "通过类名访问" << endl;Son::func();Son::Base::func();Son::Base::func(100);
}int main()
{test01();cout << endl;test02();system("pause");return 0;
}

区别仅在于静态成员有两种访问方式

菱形继承

能看懂即可

概念:
两个派生类继承一个基类
又有某个类同时继承这两个类

典型案例:

#include <iostream>
#include <string>
using namespace std;class Animal
{
public:int m_Age;
};//利用虚继承 解决菱形继承的问题
//在继承之前加上关键字 virtual 变为虚继承
//Animal类称为虚基类
class Yang :virtual public Animal {};class Tuo :virtual public Animal {};class YangTuo :public Yang, public Tuo {};void test01()
{YangTuo yt;yt.Yang::m_Age = 18;yt.Tuo::m_Age = 24;//当菱形继承,两个父类拥有相同数据,需要加以作用域区分cout << "yt.Yang::m_Age =" << yt.Yang::m_Age << endl;cout << "yt.Tuo::m_Age =" << yt.Tuo::m_Age << endl;//virtual修饰后cout << "yt.m_Age =" << yt.m_Age << endl;
}int main()
{test01();system("pause");return 0;
}

三、多态

多态分为两类:

静态多态:函数重载,运算符重载,复用函数名
动态多态:派生类和虚函数实现运行

区别:

静态多态的函数地址早绑定,编译阶段确定函数地址
动态多态的函数地址晚绑定,运行阶段确定函数地址

#include <iostream>
using namespace std;class Animal
{
public://虚函数virtual void speak(){cout << "动物在说话" << endl;}};class Cat :public Animal
{
public:void speak(){cout << "猫在说话" << endl;}
};class Dog :public Animal
{
public:void speak(){cout << "狗在说话" << endl;}
};//执行说话的函数
void doSpeak(Animal& animal)
{animal.speak();
}void test01()
{Cat cat;doSpeak(cat);Dog dog;doSpeak(dog);
}int main()
{test01();
}

动态多态满足条件

1.有继承关系
2.子类重写父类的虚函数

动态多态使用

父类的指针或者引用 执行子类对象

多态使用条件:

父类指针或引用指向子类对象

重写:
函数返回值类型 函数名 参数列表 完全一致称为重写

多态优点:

1.代码组织结构清晰
2.可读性强
3.利于前期和后期的扩展及维护

案例

》》实现计算器(两种写法)

普通写法:

#include <iostream>
#include <string>
using namespace std;class Calculator
{
public:int getResult(string oper){if (oper == "+"){return m_Num1 + m_Num2;}else if (oper == "-"){return m_Num1 - m_Num2;}else if (oper == "*"){return m_Num1 * m_Num2;}//如果想扩展新的功能,需要修改源码}int m_Num1, m_Num2;
};void test01()
{//创建计算器对象Calculator c;c.m_Num1 = 10;c.m_Num2 = 20;cout << c.m_Num1 << "+" << c.m_Num2 << "=" << c.getResult("+") << endl;cout << c.m_Num1 << "-" << c.m_Num2 << "=" << c.getResult("-") << endl;cout << c.m_Num1 << "*" << c.m_Num2 << "=" << c.getResult("*") << endl;
}int main()
{test01();system("pause");return 0;
}

在真实开发中,提倡 开闭原则
对扩展进行开发,对修改进行关闭

多态写法:

#include <iostream>
#include <string>
using namespace std;//利用多态实现计算器//实现计算器抽象类
class AbstractCalculator
{
public:virtual int getResult(){return 0;}int m_Num1;int m_Num2;
};//加法计算器
class AddCalculator :public AbstractCalculator
{
public:int getResult(){return m_Num1 + m_Num2;}};//减法计数器class SubCalculator :public AbstractCalculator
{
public:int getResult(){return m_Num1 - m_Num2;}
};//乘法计算器class MulCalculator :public AbstractCalculator
{
public:int getResult(){return m_Num1 * m_Num2;}
};void test01()
{//多态使用条件//父类指针活引用指向子类对象//加法运算AbstractCalculator* abc = new AddCalculator;abc->m_Num1 = 10;abc->m_Num2 = 20;cout << abc->m_Num1 << "+" << abc->m_Num2 << "=" << abc->getResult() << endl;//用完后记得销毁delete abc;//减法运算abc = new SubCalculator;abc->m_Num1 = 100;abc->m_Num2 = 100;cout << abc->m_Num1 << "" << abc->m_Num2 << "=" << abc->getResult() << endl;delete abc;
}int main()
{test01();system("pause");return 0;
}

纯虚函数和抽象类

在多态中,通常父类中虚函数的实现毫无意义,主要都是调用子类重写的内容

因此可以将虚函数改为纯虚函数

纯虚函数语法:
virtual 返回值类型 函数名 (参数列表)=0

当类中有了春旭函数,这个类也称为抽象类

抽象类特点:

1.无法实例化对象
2.子类必须重写抽象类中的纯虚函数,否则也属于抽象类

#include <iostream>
#include <string>
using namespace std;//纯虚数和抽象类
class Base
{
public://纯虚函数//只要有一个纯虚函数,这个类称为抽象类virtual void func() = 0;};class Son :public Base
{
public:virtual void func(){cout << "func()调用" << endl;};//子类必须重写父类中的纯虚函数,否则无法实例化对象
};void test01()
{Base * base = new Son;base->func();
}int main()
{test01();system("pause");return 0;
}

虚析构和纯虚析构

多态使用中,如果子类中有属性开辟到堆区,父类指针在释放时无法调用到子类的析构代码

解决方式: 将父类中的析构函数改为虚析构或者纯虚析构

虚析构

#include <iostream>
#include <string>
using namespace std;//虚析构和纯虚析构
class Animal
{
public:Animal(){cout << "Animal构造函数调用" << endl;}//纯虚函数virtual void speak() = 0;virtual ~Animal()	//虚析构{cout << "Animal析构函数调用" << endl;}
};class Cat :public Animal
{
public :Cat(string name){cout << "Cat构造函数调用" << endl;m_Name = new string(name);}virtual void speak(){cout <<*m_Name<<"在说话" << endl;}string *m_Name;~Cat(){if (m_Name != NULL){cout << "Cat析构函数调用" << endl;delete m_Name;m_Name = NULL;}}
};void test01()
{Animal* animal = new Cat("Tom");animal->speak();//父类指针在析构时,不会调用子类析构函数,导致子类中如果有堆区属性,出现内存泄露delete animal;
}int main()
{test01();
}

利用虚析构可以解决父类指针释放子类对象时不干净的问题

纯虚析构

#include <iostream>
#include <string>
using namespace std;//虚析构和纯虚析构
class Animal
{
public:Animal(){cout << "Animal构造函数调用" << endl;}virtual void speak() = 0;//纯虚函数virtual ~Animal()=0;	//纯虚析构};Animal::~Animal()
{cout << "Animal纯虚析构函数调用" << endl;
}class Cat :public Animal
{
public :Cat(string name){cout << "Cat构造函数调用" << endl;m_Name = new string(name);}virtual void speak(){cout <<*m_Name<<"在说话" << endl;}string *m_Name;~Cat(){if (m_Name != NULL){cout << "Cat析构函数调用" << endl;delete m_Name;m_Name = NULL;}}
};void test01()
{Animal* animal = new Cat("Tom");animal->speak();//父类指针在析构时,不会调用子类析构函数,导致子类中如果有堆区属性,出现内存泄露delete animal;
}int main()
{test01();
}

有了纯虚析构就属于抽象类

案例

》》电脑装载

#include <iostream>
#include <string>
using namespace std;class CPU
{
public://抽象计算函数virtual void calculate() = 0;
};class Memory
{
public://抽象存储函数virtual void storage() = 0;
};class VideoCard
{
public://抽象显示函数virtual void display() = 0;
};class Computer
{
public://Computer(CPU* cpu, VideoCard* vc, Memory* mem){m_Cpu = cpu;m_Vc = vc;m_Mem = mem;}//提供工作的函数void work(){//让零件工作起来,让零件工作起来m_Cpu->calculate();m_Vc->display();m_Mem->storage();}~Computer(){if (m_Cpu != NULL){delete m_Cpu;m_Cpu = NULL;}if (m_Vc != NULL){delete m_Vc;m_Vc = NULL;}if (m_Mem != NULL){delete m_Mem;m_Mem = NULL;}}private:CPU* m_Cpu;	//cpu零件指针VideoCard* m_Vc;	//显卡零件指针Memory* m_Mem;	//内存条
};//具体厂商
//Intel厂商
class IntelCPU :public CPU
{
public:virtual void calculate(){cout << "Intel的CPU开始计算了!" << endl;}
};class IntelVideoCard :public VideoCard
{
public:virtual void display(){cout << "Intel的显卡开始显示了!" << endl;}
};class IntelMemory :public Memory
{
public:virtual void storage(){cout << "Intel的内存条开始存储了!" << endl;}
};//联想厂商
class LenovoCPU :public CPU
{
public:virtual void calculate(){cout << "Lenovo的CPU开始计算了" << endl;}
};class LenovoVideoCard :public VideoCard
{
public:virtual void display(){cout << "Lenovo的显卡开始显示了" << endl;}
};class LenovoMemory :public Memory
{
public:virtual void storage(){cout << "Lenovo的内存条开始存储了" << endl;}
};void test01()
{//第一台电脑零件CPU* intelCPU = new IntelCPU;VideoCard* intelCard = new IntelVideoCard;Memory* intelMem = new IntelMemory;//创建第一台电脑Computer* computer1 = new Computer(intelCPU, intelCard, intelMem);computer1->work();cout << "第一台电脑开始工作" << endl;delete computer1;cout << "-----------------------" << endl;//第二台电脑零件CPU* lenovoCPU = new LenovoCPU;VideoCard* lenovoVC = new LenovoVideoCard;Memory* lenovoMem = new LenovoMemory;//创建第二台电脑Computer* computer2 = new Computer(lenovoCPU, lenovoVC, lenovoMem);computer2->work();cout << "第二台电脑开始工作" << endl;delete computer2;cout << "-----------------------" << endl;//第三台电脑组装Computer* computer3 = new Computer(new LenovoCPU, new IntelVideoCard, new LenovoMemory);computer3->work();cout << "第三台电脑开始工作" << endl;delete computer3;
}int main()
{test01();system("pause");return 0;
}

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

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

相关文章

马斯克要求推特工程师默写代码,开始着手整顿美国职场?

要说世间谁最熟悉代码&#xff0c;程序员敢说第二&#xff0c;应该没人敢称第一。但这群和代码打交道最多的人&#xff0c;也会被代码难住&#xff0c;比如被要求默写一段代码&#xff01; 最近&#xff0c;马斯克要求推特工程师默写代码登上热搜榜&#xff0c;成为网友们讨论…

互联网日报 | 3月22日 星期一 | 苹果iMac Pro全球下架;知乎更新上市招股书;字节跳动成立朝夕光年奇想基金...

今日看点 ✦ 知乎更新招股书&#xff1a;最高融资超10亿美元&#xff0c;腾讯阿里京东认购 ✦ 字节跳动成立朝夕光年奇想基金&#xff08;NIF&#xff09;&#xff0c;将投资游戏创业团队 ✦ 京东云联合京东物流、京东生鲜共同打造“京东冷链溯源平台” ✦ 工商银行资产托管规模…

关于苹果开发者协议更新的相关问题

最近进入开发者中心相信大家都会看到如下图所示的信息&#xff0c;同时最近很多道友在群里咨询有关开发者协议更新的问题&#xff0c;基本可以肯定的是密保问题答案给忘记了&#xff0c;忘记密保问题就真的不能更细协议了&#xff1f;当然不是&#xff0c;接下里就给大家介绍一…

ChatGLM2-6B、ChatGLM-6B 模型介绍及训练自己数据集实战

介绍 ChatGLM-6B是开源的文本生成式对话模型,基于General Language Model(GLM)框架,具有62亿参数,结合模型蒸馏技术,实测在2080ti显卡训练中上(INT4)显存占用6G左右, 优点:1.较低的部署门槛&#xff1a; FP16 半精度下&#xff0c;ChatGLM-6B 需要至少 13GB 的显存进行推理&a…

羊驼系列大模型和ChatGPT差多少?详细测评后,我沉默了

来源&#xff1a;机器之心 本文约5100字&#xff0c;建议阅读10分钟一番深入测评&#xff0c;结果令人深思。 总的来说&#xff0c;该测试得出的结论是&#xff1a;MPT 还没有准备好在现实世界中使用&#xff0c;而 Vicuna 对于许多任务来说是 ChatGPT (3.5) 的可行替代品。 前…

向AI提问,我是怎么做的?

AI对话与人完全不同。 人对话过程基于情感、文化背景、现状&#xff0c;需要考虑对方情绪、语气、表情等非语言因素&#xff0c;AI对话更多基于逻辑、数据、算法&#xff0c;更加注重信息传递和问题解决。 尽管各家都在推崇自然语言处理技术&#xff08;(Natural Language Pr…

24个好用到爆的Python实用技巧

作为一名数据工作者&#xff0c;我们每天都在使用 Python处理大多数工作。在此过程中&#xff0c;我们会不断学到了一些有用的技巧和窍门。 在这里&#xff0c;我尝试以 A - Z 开头的格式分享这些技巧中的一些&#xff0c;并且在本文中简单介绍这些方法&#xff0c;如果你对其中…

【研究那些事】 是谁可以当律师、看梗图、写代码、看论文还有创意?

0326 ChatGPT4 3月15日凌晨&#xff0c;OpenAI 正式公布了它的多模态大语言模型 GPT-4。 GPT-4 是世界第一款高体验、强能力的先进AI系统。ChatGPT用的语言模型是 GPT-3.5&#xff0c;OpenAI 称当任务的复杂性达到足够的阈值&#xff0c;GPT-4对比之前的版本的优势就会非常明显…

新星计划、原力计划新动态,大波的奖牌来袭速来领取

catalogue &#x1f31f; 写在前面&#x1f31f; 原力计划&#x1f31f; 新星计划&#x1f31f; 大波奖牌来袭&#x1f31f; 微软学生开发者峰会&#x1f31f; 写在最后 &#x1f31f; 写在前面 哈喽&#xff0c;大家好&#xff0c;我是几何心凉&#xff0c;这是一份全新的专栏…

与AI相遇 | 在ChatGPT中输入“情人节”,我们会得到......?

最近ChatGPT可谓是风靡全球&#xff0c;大家彼此的问候从“你吃饭了吗”变成“你玩ChatGPT了吗”。 这款当今最火爆的AI语言模型&#xff0c;是美国人工智能研究实验室OpenAI新推出的一种人工智能技术驱动的自然语言处理工具&#xff0c;使用了Transformer神经网络架构&#xf…

JAVA在线考试管理系统(源代码+论文+开题报告+外文翻译+英文文献+答辩PPT)

附件5&#xff1a; 毕业论文&#xff08;设计&#xff09;外文资料译文 论文题目 在线考试系统 . 学生姓名&#xff1a; 年级&#xff08;学号&#xff09;&#xff1a; . 二级学院&#xff1a; 专业&#xff1a; 指导教师&#xff1a; 职称&#xff1a; . 填表日期&…

计算机辅助翻译实践总结,trados计算机辅助翻译实践报告材料

trados计算机辅助翻译实践报告材料 (22页) 本资源提供全文预览&#xff0c;点击全文预览即可全文预览,如果喜欢文档就下载吧&#xff0c;查找使用更方便哦&#xff01; 19.90 积分 &#xfeff;实用文档研究生课程考核试卷(适用于课程论文、提交报告)科 目&#xff1a; 计算机…

热门精选!10款学习办公必备的AI笔记工具

​人工智能随着时间的推移不断发展并改变各行各业的方式令人印象深刻&#xff0c;chatGPT的出现让我们使用AI人工智能提高工作效率变得更简单。你是否厌倦了在会议期间手动记笔记&#xff1f; 在 AI 笔记工具的帮助下&#xff0c;我们可以通过自动识别和分类关键信息、总结文本…

vxe-table高级导出功能,导出表格样式

做为技术人员我们得感谢那么提出各种奇葩需求的人&#xff0c;因为他们才使我们更快成长。如果你干不掉那些提出需求的人&#xff0c;那么就接受吧&#xff0c;废话止于此。 先看下导出表格的效果 vxe-table的高级导出功能的弹窗里虽然有样式的勾选项&#xff0c;但是还需要你…

修改程序图标

看图&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;

修改应用程序图标

修改应用程序图标 众所周知&#xff0c;我们平常习惯用的Windows操作系统&#xff0c;我们可以根据个人喜好随意修改桌面图标&#xff08;可修改的图标有&#xff1a;我的电脑、我的文档、网上邻居和回收站。当然&#xff0c;其它应用程序的图标也可以修改&#xff0c;不过不是…

Launcher修改--修改底部图标

在android2.2中&#xff0c;launcher的底部被修改成这种模式&#xff0c;有时候修改launcher的时候需要去掉电话和浏览器两项&#xff0c;我们可以在res/layout-port/文件夹中找到launcher.xml文件&#xff0c;在其中有以下代码 <RelativeLayoutandroid:id"id/all_apps…

linux修改文件图标,Gnome怎么修改应用图标icon

icon元素包括两个可选的子元素&#xff1a;small-icon子元素和large-icon子元素。文件名是Web应用归档文件(WAR)的根的相对路径。部署描述符并没有使用icon元素。下面跟着学习啦小编一起来了解一下Gnome怎么修改应用图标icon的方法吧。 Gnome怎么修改应用图标icon 我在我机器上…

Android 实现App修改应用图标

Android 实现App修改应用图标 首先上一下效果图 是在不同的android版本下运行后的效果&#xff1a; 首先是8.0以上系统 运行后图标如下&#xff1a; 然后是在API为18的4.0android系统上的运行效果&#xff1a; 其他API也是兼容的。 实现过程 第一步&#xff0c;选择你喜…

修改app图标

修改app图标 1.准备三个尺寸的.png图片 &#xff08;注&#xff1a;一定要是.png后缀的图片&#xff09;,分别命名为xx.png, xx2x.png, xx3x.png; 2.在项目中找到项目->Resource->AppLogo,把三个尺寸的图片拉入项目中&#xff0c;选择Copy items if needed、Create gr…