目录
对象的初始化和清理
构造函数和析构函数
构造函数
构造函数的分类和调用
拷贝构造函数的调用时机
构造函数的调用规则
深拷贝和浅拷贝*
初始化列表
类对象作为类成员
静态成员(static)
析构函数
对象模型和this指针
this指针
空指针访问成员函数
const修饰成员函数
对象的初始化和清理
c++中的面向对象来源于生活,每个对象都会有初始设置以及对象销毁前的清理数据的设置
构造函数和析构函数
- 编译器自动调用,完成对象初始化和清理工作
- 如果程序员不自行实现,编译器提供的都是空实现
构造函数
作用:创建对象时为对象的成员属性赋值,编译器自动调用,无须手动调用
语法: 类名 () {}
- 没有返回值,也不用写void
- 函数名称与类名相同
- 可有参数,可重载
- 自动调用,无须手动调用且只调用一次
构造函数的分类和调用
分类:有参构造和无参构造(按参数)、普通构造和拷贝构造(按类型)
调用方法:括号法、显示法、隐式转换法
匿名对象:执行结束后,立即释放该对象。
注意:
1.创建对象时调用默认构造函数的时候不要加(),编译器认为是一个函数声明;
2.不要使用拷贝构造函数初始化匿名对象,编译器认为是一个对象声明;
拷贝构造函数的调用时机
1.使用创建完毕的对象初始化一个新对象
2.值传递的方式给函数参数传值
3.以值方式返回局部对象
#include <iostream>
using namespace std;class Cube
{
public:int m_L;Cube(){cout << "Cube 无参默认构造函数 调用" << endl;}Cube(int a){m_L = a;cout << "Cube 有参构造函数 调用" << endl;}Cube(const Cube &p){m_L = p.m_L;cout << "Cube 拷贝构造函数 调用" << endl;}~Cube(){cout << "Cube 析构函数 调用" << endl;}
};//使用创建完毕的对象初始化一个新对象
void test01()
{Cube p1(20);Cube p2(p1); cout << "p2 m_L value:" << p2.m_L << endl;}//值传递的方式给函数参数传值
void dowork1(Cube p)
{cout << "p m_L value:" << p.m_L << endl;
}void test02()
{Cube s1(30);dowork1(s1);
}//以值方式返回局部对象
Cube dowork2(void)
{Cube m1(40);cout << (int*)&m1 << endl;return m1;
}void test03()
{Cube m = dowork2();cout << (int*)&m << endl;cout << "m m_L value:" << m.m_L << endl;
}int main(void)
{test01();test02();test03();system("pause");return 0;
}
构造函数的调用规则
默认情况,编译器至少给一个类添加三个函数:
1.默认构造函数(无参,函数体为空)
2.默认析构函数(无参,函数体为空)
3.默认拷贝构造函数,对属性进行值拷贝
调用规则:
1.如果用户定义有参构造函数,c++不再提供默认无参构造,但会提供默认拷贝构造
2.如果用户定义拷贝构造函数,c++不再提供其它构造函数
深拷贝和浅拷贝*
浅拷贝:简单的赋值拷贝操作
深拷贝:在堆区重新申请空间,进行拷贝操作
#include <iostream>using namespace std;class Cube
{
public:int m_L;int* p_H;Cube(){cout << "Cube 无参默认构造函数 调用" << endl;}Cube(int a, int Hight){m_L = a;p_H = new int(Hight);cout << "Cube 有参构造函数 调用" << endl;}//自行实现拷贝构造函数,解决浅拷贝的问题Cube(const Cube& p){m_L = p.m_L;p_H = new int(*p.p_H); //深拷贝}~Cube(){if (p_H != NULL){delete p_H;p_H = NULL;}cout << "Cube 析构函数 调用" << endl;}
};//浅拷贝,问题:堆区的内存重复释放,使用深拷贝解决
void test01()
{Cube p1(20, 40);cout << "p1 m_L and p_H value:" << p1.m_L << "," << *p1.p_H << endl;Cube p2(p1); cout << "p2 m_L and p_H value:" << p2.m_L << "," << *p2.p_H << endl;
}int main(void)
{test01();system("pause");return 0;
}
初始化列表
作用:用于初始化属性
语法:构造函数(): 属性1(值1),属性2(值2)...{}
#include <iostream>using namespace std;class Cube
{
public:int m_L;int m_H;//初始化列表初始化属性Cube(int a, int b) :m_L(a), m_H(b){}
};int main(void)
{Cube p1(10, 20);cout << "p1 m_L and p_H value:" << p1.m_L << "," << p1.m_H << endl;system("pause");return 0;
}
类对象作为类成员
c++类中的成员可以是另一个类的对象;
注意:先构造类对象,再构造自身;析构与构造相反。
#include <iostream>
#include <string>using namespace std;class Phone
{
public:string m_phname;Phone(string pname){m_phname = pname;cout << "Phone 构造函数调用" << endl;}~Phone(){cout << "Phone 析构函数调用" << endl;}
};class Person
{
public:string m_name;Phone m_phone;//初始化列表初始化属性Person(string name, string phname) :m_name(name), m_phone(phname){cout << "Person 构造函数调用" << endl;}~Person(){cout << "Person 析构函数调用" << endl;}
};void test()
{Person p1("zhangsan", "HUAWEI");cout << p1.m_name << "拿着" << p1.m_phone.m_phname << "手机!" << endl;
}int main(void)
{test();system("pause");return 0;
}
静态成员(static)
-
静态成员变量
1.所有对象共享同一份数据
2.在编译阶段分配内存
3.类内声明,类外初始化
- 静态成员函数
1.所有对象共享同一个函数
2.静态成员函数只能访问静态成员变量
#include <iostream>
#include <string>using namespace std;class Person
{
public:int m_B;static int phone_number;static void func(){phone_number = 900;cout << "static void func()调用" << endl;}
private:static int number; //也可以访问static void func2(){phone_number = 900;cout << "static void func2()调用" << endl;}
};int Person::phone_number = 123;
int Person::number = 123;void test()
{Person p1;p1.phone_number = 100;p1.func();cout << "p1.phone_number:" << p1.phone_number << endl;Person p2;p2.phone_number = 200;cout << "p1.phone_number:" << p1.phone_number << endl;cout << "p1.phone_number:" << p2.phone_number << endl;Person::func();//Person::func2(); //私有的无法访问cout << "phone_number:" << Person::phone_number << endl; //通过类名访问//cout << "phone_number:" << Person::number << endl; //私有的无法访问
}int main(void)
{test();system("pause");return 0;
}
析构函数
作用:对象销毁前系统自动调用,执行一些清理工作
语法: ~类名() {}
- 没有返回值,也不用写void
- 函数名称与类名相同,在名称前加上符号~
- 无参数,无法重载
- 自动调用,无须手动调用且只调用一次
#include <iostream>using namespace std;class Cube
{
public:int m_L;Cube(){cout << "Cube 无参默认构造函数 调用" << endl;}Cube(int a){m_L = a;cout << "Cube 有参构造函数 调用" << endl;}//拷贝构造函数Cube(const Cube &p){m_L = p.m_L;cout << "Cube 拷贝构造函数 调用" << endl;}~Cube(){cout << "Cube 析构函数 调用" << endl;}
};void test01()
{//括号法Cube p1; //无参Cube p2(20); //有参Cube p3(p2); //拷贝cout << "p2 m_L:" << p2.m_L << endl;cout << "p3 m_L:" << p3.m_L << endl;//显示法Cube s1;Cube s2 = Cube(10);Cube s3 = Cube(s2);//Cube(10); //匿名对象,特点:当前行执行结束后,立即释放该对象。cout << "s2 m_L:" << s2.m_L << endl;cout << "s3 m_L:" << s3.m_L << endl;//Cube(s3); 相当于 Cube s3; 不要使用拷贝构造函数初始化匿名对象//隐式转换法Cube s4 = 15;Cube s5 = s4;cout << "s4 m_L:" << s4.m_L << endl;cout << "s5 m_L:" << s5.m_L << endl;
}int main(void)
{test01();system("pause");return 0;
}
对象模型和this指针
成员变量和成员函数分开存储,只有非静态成员变量才属于类的对象上
#include <iostream>
#include <string>using namespace std;class Person
{int m_A; //非静态成员变量,属于类的对象上static int m_B; //静态成员变量,不属于类的对象上void func() //非静态成员函数,不属于类的对象上{}static void func1() //静态成员函数,不属于类的对象上{}
};void test()
{Person p;//空对象占用内存空间为:1,为了区分多个空对象占内存的位置,每个空对象的内存都是唯一的;cout << "size of p = " << sizeof(p) << endl;
}void test02()
{Person p;cout << "size of p = " << sizeof(p) << endl;
}int main(void)
{test();test02();system("pause");return 0;
}
this指针
this指针指向被调用的成员函数所属的对象
1.隐含每一个非静态成员函数内的一种指针
2.不需要定义,直接使用
用途:
1.当形参和成员变量同名时,可以使用this指针区分
2.在类的非静态成员函数中返回对象本身,可以使用 return *this
#include <iostream>
#include <string>using namespace std;class Person
{
public:int age;Person(int age){//指向 被调用的成员函数 所属的对象this->age = age;}Person& PersonAddAge(Person p) //如果用值Person返回 ,会创建一个新的对象{this->age += p.age;return *this;}
};//1.解决名称冲突
void test()
{Person p1(10);cout << "p1 age = " << p1.age << endl;}void test1()
{Person p1(10);Person p2(10);//链式 编程思想p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1);cout << "p2 age = " << p2.age << endl;}//2.返回对象本身用*thisint main(void)
{test();test1();system("pause");return 0;
}
空指针访问成员函数
c++空指针可以访问成员函数,如果用到this指针要判断保证代码的健壮性
#include <iostream>
#include <string>using namespace std;class Person
{
public:int m_Age;void showClassName(){cout << "this is Person Class" << endl;}void showPersonAge(){if (this == NULL)return;cout << "age=" << m_Age << endl;}
};void test()
{Person* p = NULL;p->showClassName();p->showPersonAge();}int main(void)
{test();system("pause");return 0;
}
const修饰成员函数
常函数:
1.成员函数后加const后成为常函数
2.常函数内不可以修改成员属性
3.成员属性声明时加关键字mutable后,在常函数中依然可以修改
常对象:
1.声明对象前加const称为常对象
2.常对象只能调用常函数
#include <iostream>
#include <string>using namespace std;class Person
{
public:int m_Age;mutable int m_B; //mutable 常函数中也可以修改Person(int a, int b){m_Age = a;m_B = b;}//this指针的本质: 指针常量 指针的指向不可以修改 Person * const this;void showClassName(int b) const //修饰的this指针,相当于const Person * const this,让指针指向的值也不可以修改;{//this->m_Age = 100; 错误 无法修改this->m_B = b;}void func(){cout << "void func()" << endl;}
};void test()
{Person p(1,2);p.showClassName(50);cout << "m_Age:" << p.m_Age << "\tm_B:" << p.m_B << endl;const Person m(4,5); //m.m_Age = 10; 无法调用m.m_B = 30;m.showClassName(100);//常函数只能调用常函数//m.func();cout << "m_Age:" << m.m_Age << "\tm_B:" << m.m_B << endl;
}int main(void)
{test();system("pause");return 0;
}
推荐文章:[C++核心编程](四):类和对象——封装