C++面向对象编程
概述面向对象与面向过程的区别对象的描述及其类型创建对象 与 创建对象指针构造函数this指针析构函数拷贝构造函数C++类的三大特征
概述
一切皆对象,一个程序就是由一组对象组成的一个整体,程序的功能是通过对象之间传递消息来完成的。
面向对象与面向过程的区别
例如:把大象装进冰箱需要几步,两者的解决方法:
面向过程:打开冰箱–>把大象塞进去–>关冰箱 面向对象:调用一个具有将大象塞进冰箱的类的功能
对象的描述及其类型
对象由共同特征和功能组成: * 使用变量描述共同特征 * 使用函数描述功能
举例: *学生的共同特征为:学号、姓名、班级…… *学生的功能为:吃饭、睡觉、学习……
对象类型的描述 (1) 使用结构体(struct)描述: 结构体中既可以有成员变量,也可以有成员函数。因此结构体可以来 表示对象类型,在C++中,对象的类型叫做类。
(2) 使用struct实现时间对象实例
#include <iostream>
#include <unistd.h>
using namespace std
;
struct Time
{
int hour
;
int min
;
int sec
;
void print_time(){
cout
<<hour
<<":"<<min
<<":"<<sec
<<endl
;
}
void set_time(int h
=15,int m
=30,int s
=25){
hour
= h
;
min
= m
;
sec
= s
;
}
void run(){
sec
++;
if(sec
==60){
sec
= 0;
min
++;
if(min
==60){
min
= 0;
hour
++;
if(hour
==24)
hour
= 0;
}
}
}
};
int main()
{
Time t
;
t
.hour
= 1;
t
.min
= 2;
t
.sec
= 3;
t
.print_time();
t
.set_time(23,59,49);
while(1){
t
.run();
t
.print_time();
sleep(1);
}
return 0;
}
(3)使用类(class)描述: ①:class也可以用来描述对象类型,语法和struct几乎一致。 ②:具有访问属性:public — 公有属性、protected — 受保护属性、 private — 私有属性。 ③:因struct声明的类中的成员默认是公开的,class声明的类中成员默认是私有的。所以 在C++中一般不使用struct而使用class来声明类。
(4)使用class实现时间对象实例
#include <iostream>
using namespace std
;
class Time{
private:
int hour
;
int min
;
protected:
int sec
;
public:
void print_time(){
cout
<<hour
<<":"<<min
<<":"<<sec
<<endl
;
}
void set_time(int h
=15,int m
=30,int s
=25){
hour
= h
;
min
= m
;
sec
= s
;
}
void xxx(){
print_time();
}
void set_hour(int h
=100){
hour
= h
;
}
int get_hour(){
return hour
;
}
};
int main(void)
{
Time t
;
t
.set_time();
t
.print_time();
t
.xxx();
return 0;
}
创建对象 与 创建对象指针
1.创建对象
类名 对象名 默认调用“对象名()”这个构造函数,在栈内存中存在对象名,在堆内存中存在实际对象;类名 对象名(一个或以上个参数) 默认调用相应的构造函数,在栈内存中存在对象名,在堆内存中也是存在实际对象的;类名 对象名() 不调用任何构造函数创建对象,仅在栈内在中存在对象名,在堆内存中并不存在实际的对象;
2.创建对象指针
对象指针:类名 *对象指针名 new创建放在自由存储区,需要手动delete,才能调用析构函数,类似C中的malloc,其对应C中的堆,需要手动free,才能释放内存,其他创建方式放在栈中
构造函数
构造函数的作用是初始化对象,处于类内部;构造函数是一个特殊的函数,函数名和类名相同,没有返回值类型;构造函数会在类构造对象时自动调用一次;构造函数必须是公有属性;如果类没有构造函数,编译器在编译时会自动生成一个构造函数,这个构造函数什么都不做;类应该提供构造函数。
#include <iostream>
#include <cstdlib>
using namespace std
;
class A{
public:
A(){cout
<<"我是A"<<endl
;}
};
class Animal{
private:
int age
;
float weight
;
string name
;
A a
;
public:
Animal(){
cout
<<"我是Animal"<<endl
;
name
= "xiaohua";
weight
= 21.3f;
age
= 5;
}
Animal(int m_age
,float m_weight
=21.5f,string m_name
="xiaohuang"){
cout
<<"Animal(int,float,string)"<<endl
;
name
= m_name
;
weight
= m_weight
;
age
= m_age
;
}
void show(){
cout
<<name
<<":"<<age
<<":"<<weight
<<endl
;
}
};
int main()
{
Animal
an(4,11.2,"xiaofei");
an
.show();
return 0;
}
注意:当类中有引用,const等成员时,需要在调用构造函数之前进行初始化
#include <iostream>
using namespace std
;
class Animal{
private:
int age
;
float weight
;
string name
;
int &num
;
const int height
;
public:
Animal(int m_age
,float m_weight
,string m_name
,int m_height
):
age(m_age
),weight(m_weight
),name(m_name
),num(age
),height(m_height
){
cout
<<"Animal(int,float,string,int)"<<endl
;
}
void show(){
cout
<<name
<<":"<<num
<<":"<<height
<<endl
;
}
};
int main()
{
Animal
an(5,11.2f,"ahuang",30);
an
.show();
return 0;
}
this指针
概念: this指针在类内部的成员函数和构造函数中,代表调用该成员函数的对象或正在构造的对象。使用方法: ① 可以在成员函数和构造函数中,使用this指针对重名的函数形参和成员变量做一个区分 ② 可以作为成员函数的参数和返回值 ③this指针是指向对象的,它代表对象的首地址。
#include <iostream>
#include <string>
using namespace std
;
class Animal;
void show_Animal(Animal
&an
);
class Animal{
private:
string name
;
int age
;
double weight
;
public:
Animal(string name
,int age
,double weight
){
cout
<<"Animal()"<<endl
;
this->name
= name
;
this->age
= age
;
this->weight
= weight
;
}
Animal
*show(){
show_Animal(*this);
cout
<<this->name
<<":"<<this->age
<<":"<<this->weight
<<endl
;
return this;
}
void run(){
cout
<<"Animal run!"<<endl
;
}
};
void show_Animal(Animal
&an
)
{
cout
<<"show_Animal()"<<endl
;
an
.run();
}
int main()
{
Animal
*pa
= new Animal("xiaohua",2,24.4);
pa
->show();
delete pa
;
return 0;
}
运行结果:
析构函数
概念: ①是一个特殊的函数,函数名和类名相同,但是前面要加一个~,不能有任何参数,也没有返回值; ②析构函数在对象被销毁释放时会被自动调用一次; ③如果类中没有析构函数,编译器会自动生成一个什么也不做的析构函数。
用法:如果在销毁对象时需要释放资源,比如动态内存在构造函数中申请了动态内存(new),在析构函数中使用(delete)。
拷贝构造函数
概念:拷贝构造函数是一个特殊的构造函数,当使用一个已经存在的对象去创建另一个同类型的新对象时会调用拷贝构造函数。用法: ①:用已有的对象去构造新对象,例如: A a; A b = a; //拷贝构造; ②:把一个对象传递给同类型的形参; ③:把一个对象作为函数的返回值。需要构造的情况:当对象内部存在独立内存时需要自定义拷贝,例如数组,指针等。注意: ①:拷贝构造是将对象的数据逐字拷贝; ②:不同的对象不可以使用同一片内存,所以需要自定义拷贝函数; ③:系统默认的拷贝构造属于浅拷贝;为独立内存重新分配空间,拷贝空间中的内容叫深拷贝。
#include <iostream>
#include <cstring>
using namespace std
;
class Date{
private:
int year
;
int month
;
int day
;
char *str
;
public:
Date(int year
=2020,int month
=9,int day
=29,const char *str
="welcome"){
this->year
= year
;
this->month
= month
;
this->day
= day
;
this->str
= new char[strlen(str
)+1];
strcpy(this->str
,str
);
}
~Date(){
delete[] this->str
;
}
Date(const Date
&dt
){
this->year
= dt
.year
;
this->month
= dt
.month
;
this->day
= dt
.day
;
this->str
= new char[strlen(dt
.str
)+1];
strcpy(this->str
,dt
.str
);
cout
<<"Date(const Date &dt)"<<endl
;
}
void set_str(const char *str
){
strcpy(this->str
,str
);
}
void show(){
cout
<<this->str
<<":"<<this->year
<<"-"<<this->month
<<"-"<<this->day
<<endl
;
}
};
int main(void)
{
Date
dt(2018,8,8);
Date dt1
= dt
;
dt
.show();
dt1
.show();
dt
.set_str("hello");
dt
.show();
dt1
.show();
return 0;
}
C++类的三大特征