对象的初始化和清理
#include<iostream>
#include<string>
using namespace std;
//构造函数:初始化
//析构函数:清理
class Person
{
public:
//1.构造函数
//构造函数没有返回值 不用写void
//函数名 与类名相同
//可以有参数 可以发生重载
//创建对象时,构造函数会自动调用,只调用一次
Person()
{
cout<<"构造函数的调用"<<endl;
}
//2.析构函数
// 没有返回值 不用写void
//函数名 与类名相同 在名称前写~
//不能有参数 不可以发生重载
//对象销毁前,会自动调用析构函数,只调用一次
~Person()
{
cout<<"析构函数的调用"<<endl;
}
} ;
int main(){
Person p; //在栈上的数据
return 0;
}
构造函数的分类和调用
#include<iostream>
#include<string>
using namespace std;
//构造函数的分类
//按参数分:有参构造和无参构造
//按类型分:普通构造和拷贝构造
//三种调用方式:括号法 显示法 隐式转换法
class Person
{
public:
//构造函数 :普通
Person()//无参构造 默认构造
{
cout<<"构造函数的调用"<<endl;
}
Person(int a)//有参构造
{
age=a;
cout<<"有参构造函数的调用"<<endl;
}
//拷贝构造函数
Person(const Person &p)
{
//将传入的人身上所有的属性 拷贝到我身上
age=p.age;
cout<<"拷贝构造函数的调用"<<endl;
}
~Person()
{
cout<<"析构函数的调用"<<endl;
}
int age;
} ;
void test01()
{
//1、括号法
Person p1;//默认构造函数调用 加括号会被认为是函数声明,不会认为实在创建对象
Person p2(10);//有参构造函数调用
Person p3(p1);
//2、显示法
Person p11;
Person p22=Person(10);//Person(10)是一个匿名对象 匿名对象当前行结束后系统会自动回收
Person p33=Person(p2);
//3、隐式转换法
Person p4=10;//相当于写了Person p4=Person(10);
Person p5=p4;//Person p5=Person(p4)
}
int main(){
test01();
return 0;
}
拷贝构造函数的调用时机
//拷贝构造函数调用时机
//1、使用一个已经创建完毕的对象来初始化一个新对象
//2、值传递的方式给函数参数传值
//3、值方式返回局部对象
构造函数调用规则
只要创建一个类 编译器会提供三个默认函数
1.默认构造函数 (无参,空实现)
2.默认析构函数(无参,空实现)
3.默认拷贝构造函数,对值属性进行拷贝
调用规则如下
1.如果我们定义有参构造函数,编译器不会提供默认构造函数,但提供默认拷贝构造函数
2.如果用户定义了拷贝构造函数,编译器将不会提供其他构造函数
深拷贝与浅拷贝
#include<iostream>
using namespace std;
//深拷贝与浅拷贝
class Person
{
public:
Person()
{
cout<<"Person默认构造函数调用"<<endl;
}
Person(int age,int height)
{
cout<<"Person有参构造函数调用"<<endl;
m_age=age;
m_height=new int(height);//new创建堆区的空间 返回了地址 所以用指针接受
}
person(const Person &p)
{
cout<<"拷贝构造函数调用"<<endl;
m_age=p.m_age;
//m_height_=p.m_height;编译器默认实现
//深拷贝操作
m_height=new int(*p.m_height);//开辟一个新的空间放变量
}
~Person()
{
//将堆区开辟的数据做释放操作
if(m_height!=NULL)
{
delete m_height;
m_height=NULL;//防止野指针出现
//如果进行浅拷贝 内存会释放两次出错
}
cout<<"Person析构函数调用"<<endl;
}
int m_age;
int*m_height;
} ;
void test01()
{
Person p1(20,160);
cout<<"p1的年龄为"<<p1.m_age<<"身高为"<<*p1.m_height<<endl;
Person p2(p1); //p1初始化p2
cout<<"p2的年龄为"<<p2.m_age<<"身高为"<<*p2.m_height<<endl;//编译器的默认拷贝参数进行值传递
}
int main(){
test01();
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(10,20,30);
cout<<"m_a="<<p.m_a<<endl;
cout<<"m_b="<<p.m_b<<endl;
cout<<"m_c="<<p.m_c<<endl;
}
int main(){
test01();
return 0;
}
对象成员
#include<iostream>
#include<string>
using namespace std;
//类对象作为类成员
//c++类中的成员可以是另一个类的对象 该成员为对象成员
class Phone
{
public:
Phone(string pname)
{
m_pname=pname;//手机品牌名称
}
string m_pname;
};//m_Phone
class Person
{
public:
Person(string name,string pname):m_name(name),m_Phone(pname)
{
}
void playgame()
{
cout<<m_name<<m_Phone.m_pname<<endl;
}
//姓名
string m_name;
//手机
Phone m_Phone; //Phone对象在这里作为成员
} ;
//当其他类的对象作为本类成员 构造时先构造类对象 再构造自身 析构相反
void test01()
{
Person p("张三","华为");
p.playgame();
}
int main(){
test01();
return 0;
}
静态成员变量
#include <iostream>
using namespace std;
class Student{
public:
Student(char *name, int age, float score);
void show();
private:
static int m_total; //静态成员变量
private:
char *m_name;
int m_age;
float m_score;
};
//初始化静态成员变量
int Student::m_total = 0;
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){
m_total++; //操作静态成员变量
}
void Student::show(){
cout<<m_name<<"的年龄是"<<m_age<<",成绩是"<<m_score<<"(当前共有"<<m_total<<"名学生)"<<endl;
}
int main(){
//创建匿名对象
(new Student("小明", 15, 90)) -> show();
(new Student("李磊", 16, 80)) -> show();
(new Student("张华", 16, 99)) -> show();
(new Student("王康", 14, 60)) -> show();
return 0;
}
静态成员函数
#include<iostream>
using namespace std;
//静态成员函数
//所有对象共享一个函数
//静态成员函数只能访问静态成员变量
class Person
{
public:
static void func()
{
cout<<"静态函数调用"<<endl;
m_a=100;
}
static int m_a;
} ;
int Person::m_a=0;
void test01()
{
//通过对象访问
Person p;
p.func();
//通过类名访问
Person::func();
}
int main(){
test01();
return 0;
}
对象模型
#include<iostream>
using namespace std;
//对象模型
//成员变量和成员函数是分开存储的
//非静态成员变量 属于类的对象上(只有这个属于类对象上)
//非静态成员函数 不属于类对象上
class Person
{
public:
} ;
void test01()
{
Person p;
//空对象占用内存空间为1
cout<<"size of p:"<<sizeof(p)<<endl;
}
int main(){
test01();
return 0;
}
this指针
#include<iostream>
using namespace std;
//this指针:指向被调用的成员函数所属的对象
//用途:解决名称冲突 ;返回对象本身用*this
class Person
{
public:
Person(int age)
{
this->age=age;
}
Person& PersonAddage(Person&p)//用引用的方式
{
this->age+=p.age;
return *this;//*this指向p2的本体
}
int age;
} ;
void test01()
{
Person p1(18);
cout<<"年龄为"<<p1.age<<endl;
}
void test02()
{
Person p1(10);
Person p2(20);
//链式编程思想
p2.PersonAddage(p1).PersonAddage(p1).PersonAddage(p1);
cout<<"p2年龄为"<<p2.age<<endl;
}
int main(){
test01();
test02();
return 0;
}
空指针可以调用成员函数
const修饰成员函数
const修饰成员函数:常函数(在后面加const,修饰this指向,让指针指向的值也不能修改)
1、常函数内不可以修改成员属性
2、成员属性声明时加关键字mutable后,就可以修改
常对象:
1、声明前加const
2、只能调用常函数