目录
对象的初始化和清理
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.返回对象本身用*this
int 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;
}