文章目录
============================ 【说明】 ===================================================
大家好,本专栏主要是跟学C++内容,自己学习了这位博主【 AI菌】的【C++21天养成计划】,讲的十分清晰,适合小白,希望给这位博主多点关注、收藏、点赞。
主要针对所学内容,通过自己的理解进行整理,希望大家积极交流、探讨,多给意见。后面也会给大家更新,其他一些知识。若有侵权,联系删除!共同维护网络知识权利!
=======================================================================================
1、面向对象(类与对象)
学过java应该知道,java一种面向对象的编程语言,C++也不例外,C++也是一种面向对象的语言。那么什么是面向对象,什么又是类,我们通过一个简答案例说明。
我们利用程序来模拟飞机,首先飞机具有相关属性,例如名称,型号,产地等等;
除此之外,还有其他功能,例如:起飞、降落、载客等等,我们可以把这些能做的事统称为方法。
在程序中,我们可以定义某种结构,这种结构包括飞机属性及飞机能做的功能,来简单模拟一架飞机,这种结构就是类。方法就是属于该类的函数。
1.1 类
上述所谓的结构可以统称为类,主要包括两部分:属性和方法。
在使用时,我们必须要声明类,声明类时注意以下几点:
(1)必须使用关键词class
,在class
后面定义一个类名。
(2)在{}
内定义相关属性和方法(函数)
(3)注意分号(;)
不要忘。
我们简单声明一个类:
#include<iostream>
using namespace std;
class Plane{
//属性
string Nmae; //名称
int Type; //型号
string place;//产地
//方法
void Fly();//起飞
void Descend();//降落
};
上述案例中,我们利用class
关键字创建了名为Plane
的类,也可以理解为Plane
是我们创建的一个数据类型,并在内部封装了属性和方法。
封装:封装是将数据和使用该数据的方法进行逻辑组合,这是面向对象编程重要特征之一(其他是抽象、继承、多态)。
1.2 对象
纸上谈兵,类就像是张规划好的纸,声明类不会对成对执行有任何影响,就如同声明一个函数不去调用,那么函数也只是一个摆设。
在程序中,对象时类的实际化。要利用类中各类功能(方法),就要实例化一个对象,并通过这个对象访问类的属性和方法,那这里的对象就好比不同型号的飞机,比如歼击机-20,侦察机等等,这些实例基本都具有类中的属性和方法。
实例化一个对象,就如同声明一个变量,前面说了我们声明的类Plane
就是我们创建的一个数据类型,例如:
int a=0;//声明一个变量、
Plane J-20;实例化一个对象J-20
之前,在【跟学C++】C/C++必学知识——指针【番外2】中学习过,利用new
关键字来为数据动态分配内存,同时利用delete
释放内存。
int *pNum = new int;
delete pNum;
在这里,我们也可以利用自己创建的数据类型Plane
,利用new
来为Plane
的对象动态分配内存空间。
//动态分配内存给Plane对象。new返回分配的内存地址给指针pPlane,也可以说pPlane指向分配的内存
Plane *pPlane=new Plane;
delete pPlane;
1.3 访问之句点运算符(.)
前面讲了,我们实例化对象,可以访问类的属性和方法,那么我们该如何或者说利用什么方式去访问呢?
第一种方式,我们可以利用句点运算符(.)
,可以访问属性和成员函数,例如上面的Plane
类,实例化一个对象J-20
,可以利用句点访问类的属性和方法:
Plane J-20;
J-20.Name="歼-20";
J-20.Fly();//访问函数
另外,当有一个指针pJ-20,指向Plane类的实例对象J-20,也可以利用句点访问:
Plane *pJ-20=new Plane();
(*pJ-20).Fly();
1.4 访问之指针运算符(->)
想要使用指针运算符->
来访问属性和方法是有条件的,对象是通过new在自由存储区中示例化,或者有指向对象的指针,那么这样可以利用指针运算符->
来访问成员属性和方法。
1、通过new来在存储区中实例化对象:
Plane *pJ-20=new Plane();
pJ-20->Nmae="歼-20";
pJ-20->Fly();
delete pJ-20;
2、指针指向对象:
Plane J-20;
Plane *pJ-20=&J-20;
pJ-20->Nmae="歼-20";
pJ-20->Fly();
delete pJ-20;
2、public(公有)和private(私有)
实际中,很多信息是保密的,为了将这些数据隐私不公开,在类中我们可以利用public(公有)和private(私有)关键字来定义属性和方法。
公有属性和方法只要有需要就可以利用对象来访问,私有属性和方法若想访问,只能在类的内部(或其友元)中访问。
比如一个案例,飞机的型号是不公开的,私密的,因此Type
作为私有属性,当你想向外部提飞机型号,可以利用公有方法setType
中,将型号值-10输出。
#include<iostream>
using namespace std;
class Plane{
private:
int Type; //型号
public:
void GetType(int inputType) {
Type = inputType;
}
int setType(){
return Type - 10;
}
};
int main() {
Plane J20;
J20.GetType(66);
Plane J30;
J30.GetType(88);
cout << "J20的型号为:" << J20.setType()<< endl;
cout << "J30的型号为:" << J30.setType() << endl;
return 0;
}
如果使用句点运算符J20.Type访问时,程序会报错,原因是Type是私有属性,无法从外部直接访问。
3、构造函数
构造函数是一种特殊的函数(方法),在创建对象时被调用。
3.1 声明与实现构造函数
构造函数有两个特点:
(1) 函数名与类名相同
(2) 函数不返回任何值
构造函数有两种构造方式:可以在类中,也可以在类外。
案例:
#include<iostream>
using namespace std;
class Human{
public:
Human() {
//函数体;
}
};
class Human {
public:
Human();//构造函数声明
};
Human::Human() {//定义构造函数
//函数体;
};
注意:(::
)表示作用域运算符
3.2 使用构造函数
构造函数是在创建函数时被调用,构造函数让类成员变量初始化的理想场所。
案例:使用构造函数为类成员变量赋值。
#include<iostream>
using namespace std;
class Human
{
private:
string Name;
int Age;
public:
Human()
{
cout << "构造函数:初始化变量Age" << endl;
Age = 0;
}
void SetName(string InputName)
{
Name = InputName;
}
void SetAge(int InputAge)
{
Age = InputAge;
}
void Introduce()
{
cout <<"I am " << Age << " years old" << endl;
}
};
int main()
{
Human Man;
Man.SetName("Jack");
Man.SetAge(18);
Man.Introduce();
return 0;
}
3.3 重载构造函数
class Human
{
public:
Human()
{
默认构造函数;
}
Human(string InputName)
{
重载构造函数;
}
};
案例:
#include<iostream>
using namespace std;
class Human
{
private:
string Name;
int Age;
public:
Human()
{
cout<<"调用构造函数:初始化变量Age"<<endl;
Age=0;
}
Human(string InputName)
{
cout<<"调用重载构造函数1:初始化变量Name"<<endl;
Age = 0;
Name= InputName;
}
Human(string InputName, int InputAge)
{
Name = InputName;
Age = InputAge;
cout<<"调用重载构造函数2:初始化变量Age、Name"<<endl;
}
void SetName(string InputName)
{
Name = InputName;
}
void SetAge(int InputAge)
{
Age = InputAge;
}
void Introduce()
{
cout<<"I am " + Name<< " and am "<<Age<<" years old"<<endl<<endl;;
}
};
int main()
{
Human Man; //实例化对象
Man.SetName("Jack");
Man.SetAge(18);
Man.Introduce();
Human Woman("Lucy"); //实例化对象,并提供了一个参数
Woman.SetAge(16);
Woman.Introduce();
Human Kid("Tom", 6); //实例化对象,并提供了两个参数
Kid.Introduce();
return 0;
}
3.4 带默认值的构造函数
class Human()
{
private:
string Name;
int Age;
public:
Human(string InputName, int InputAge=18)
{
Name = InputName;
Age = InputAge;
}
};
Human Man("Tom");
Human Woman("Lucy", 16); //这时16就会覆盖默认值
4、析构函数
与构造函数一样,析构函数也是一-种特殊的函数。 不同的是,析构函数在对象销毁时自动被调用。
其声明方式和构造函数也近似,只是在前面加了一个波浪号(~) 。如下所示:
1.类内声明
class Human
{
public:
~Human()
{
析构函数;
}
};
2.类外声明
class Human
{
public:
~Human();
};
Human::~Human()
{
构造函数;
}
什么时候使用析构函数?
每当对象不再在作用域内或通过delete被删除,进而被销毁时,都将调用析构函数。这使得析构函数是重置变量、释放动态分配内存和其他资源的理想场所。
注意:在对象创建时,编译器会自动调用构造函数;对象销毁时,将自动调用析构函数。
构造函数、析构函数都是编译器自动调用的。
5、总结
最后,长话短说,大家看完就好好动手实践一下,切记不能三分钟热度、三天打鱼,两天晒网。大家也可以自己尝试写写博客,来记录大家平时学习的进度,可以和网上众多学者一起交流、探讨,我也会及时更新,来督促自己学习进度。一开始提及的博主【AI菌】,个人已关注,并订阅了相关专栏(对我有帮助的),希望大家觉得不错的可以点赞、关注、收藏