目录
对象
从广义上讲,要在内存上一段有意义的区域就成称之为对象。
在C++中,对象一般是指泪在内存中装载的实例,具有相关的成员变量和成员函数。类是抽象的概念,而对象是通过类实现的具体实例。
构造函数和析构函数
由于对象一定会在内存中占有一段空间,所以一定会有其生命周期。也就是说对象有申请内存空间和释放内存空间的步骤。
构造函数是当对象申请内存空间之后自动调用的函数。
构造函数的声明:①构造函数的声明要在类中声明
②构造函数没有返回值
③构造函数的函数名必 必须和类名一致
析构函数是当对象的空间即将被销毁前自动调用的函数。
1.vi Student.h
#ifndef _STUDENT_
#define _STUDENT_
class Student
{
public:
char name[20];
double score;
Student();//构造函数
void Student()//类成员函数
};
#endif
构造函数的定义
定义在类外部的方式:
类名::类名(参数列表)
{
//函数体
}
2.vi Student.cpp
#include"Student.h"
#include<iostream>
using namespace std;
Student::Student()//构造函数调用
{
cout<<"Student::Student()"<<endl;
}
3.vi main.cpp
#include"Student.h"
int main(int argc,char **argv)
{
Student stu;//创建对象,此时调用无参函数
return 0;
}
析构函数的声明:①析构函数的函数名以~+类名
②析构函数没有返回值
③析构函数没有参数列表
析构函数的定义:可以在类内部定义也可以在类的外部定义
类内部定义:~类名(参数列表){ //函数体}
类外部定义:类名::~类名(参数列表){ //函数体}
#ifndef _STUDENT_
#define _STUDENT_
class Student
{
public:
char name[20];
double score;
Student();//构造函数,括号里面可空可写
~Student();//析构函数,括号里面为空
void Student()//类成员函数
};
#endif
#include"Student.h"
#include<iostream>
using namespace std;
Student::Student()//构造函数调用
{
cout<<"Student::Student()"<<endl;
}
Student::~Student()//析构函数调用
{
cout<<"Student::~Student()"<<endl;
}
对象调用公有成员:通过运算符“.”或者“->”访问对象里的公有(public)成员
#include"Student.h"
#include<string.h>
int main(int argc,char **argv)
{
Student stu;//创建对象
strncpy(stu.name,"Tom",20);//拷贝
stu.score = 100;//访问stu中的score
stu.introduce();//调用stu中的introduce
Student stu2;
Student *pStu;//指针访问
pStu = &stu2;
strncpy(pStu->name,"Jom",20);
pStu->score = 60;
pStu->introduce();
return 0;
}
运行结果
1.vi Student.h
#ifndef _STUDENT_
#define _STUDENT_
class Student
{
public:
char name[20];
double score;
void Student()//类成员函数
Student();//构造函数,括号里面可空可写
Student(const char *name);//此时默认无参构造函数不再存在
Student(const char *name,double score);
//~Student();//析构函数,括号里面为空
};
#endif
2.vi Student.cpp
#include"Student.h"
#include<iostream>
#include<string.h>
using namespace std;
void Student::introduce()//函数
{
count<<"name: "<<name<<endl;
count<<"name: "<<name<<endl;
}
Student::Student(const char* name)//构造函数调用
{
strncpy(this->name,name,20);//this->name是成员里面的指向name,而不是参数
}
Student::Student(const char* name,double score)//构造函数调用
{
strncpy(this->name,name,20);
this->score = score;
}
3. vi main.cpp
#include"Student.h"
#include<string.h>
int main(int argc,char **argv)
{
// Student stu;//创建对象,调用无参的构造函数
Student stuTom("Tom");//Student stu(const char* name)
stuTom.introduce();
cout<<"===="<<endl;//分隔符
Student stuPeter("peter",88);//Student stu(const char* name,double score)
stuPeter.introduce();
return 0;
}
运行结果
构造函数列表初始化
可以用列表初始化的方式对类成员直接赋值,这样做会提高程序运行效率。
类名::构造函数(参数1,参数2,.......)
:类成员(参数1),类成员(参数2).....
{
}
注意:列表初始化对方式只支持将参数通过赋值运算赋值给类成员。
注意:列表初始化成员的顺序必须和类成员声明的顺序一致。
1.vi Student.h
#ifndef _STUDENT_
#define _STUDENT_
class Student
{
public:
char name[20];
double score;
int age;
void Student()//类成员函数
// Student();//构造函数,括号里面可空可写
Student(const char *name);//此时默认无参构造函数不再存在
Student(const char *name,double score);
//~Student();//析构函数,括号里面为空
};
#endif
2.vi Student.cpp
#include"Student.h"
#include<iostream>
#include<string.h>
using namespace std;
void Student::introduce()//函数
{
count<<"name: "<<name<<endl;
count<<"score: "<<score<<endl;
count<<"age: "<<age<<endl;
}
Student::Student(const char* name)//构造函数调用
{
strncpy(this->name,name,20);//this->name是成员里面的指向name,而不是参数
}
Student::Student(const char* name,double score),int age//构造函数调用
:score(score),age(age)
{
strncpy(this->name,name,20);//name是用strncpy,所以name不能列表初始化
//this->score = score;
}
3.vi main.cpp
#include"Student.h"
#include<string.h>
int main(int argc,char **argv)
{
// Student stu;//创建对象,调用无参的构造函数
Student stuTom("Tom");//Student stu(const char* name)
Student stuTom = "Tom";//和Student stuTom("Tom")功能一样
stuTom.introduce();
cout<<"===="<<endl;//分隔符
Student stuPeter("peter",88,24);//Student stu(const char* name,double score)
stuPeter.introduce();
return 0;
}
运行结果
构造函数隐式调用
当构造函数只有一个参数时,就可能出现构造函数隐式调用当现象。Number i = 55;这样的现象。
55是一个整数,i是一个Number类型,这却可以让整数初始化自己定义到类型。因为在这个过程中出现了结构函数隐式调用的情况
在构造函数声明前加上explicit关键字可以关闭构造函数隐式调用功能
new和delete
new和delete是C++中的两个关键字,主要用于在向堆申请或者释放空间。
和C语言中申请堆内存不同的是,new/delete在申请/释放空间的时候还会调用构造和析构函数
new使用的方法:使用new创建对象:类名* 变量名 = new 构造函数(参数列表);
使用new创建对象数组:类名* 变量名 = new 类名[数组的大小];//此时会调用多次构造函数
delete的使用方法:使用delete销毁对象:delete 指向对象的指针;//此时会调用析构函数
使用delete销毁对象数组:delete[]对象数组名;//此时会调用多次析构函数
注意delete和delete[]的选择.
1.vi Object.h
#ifndef _OBJECT_H
#define _OBJECT_H
class Object
{
Object();//构成函数
~Object();//析构函数
}
#endif
2. vi main.cpp
#include"Object.h"
int main (int argc,char **argv)
{
//Object *p0bj = new Object();//使用new创建单个对象
//delete pObj;
Object *pOjs = new Object[5];//此时只会调用无参的构造函数
delete []pOjs;
return 0;
}
this指针
当通过对象调用成员函数传递参数时,会额外将本身的地址作为参数传递进入函数。
在函数体的内部可以通过this指针获取到编译器隐式传入的当前对象地址,并访问对象的成员。
this->类成员;