在visual studio中可直接运行
#include <iostream>
#include <string>
using namespace std;
/******************************************************************
1、构造函数和析构函数
(1)构造函数 格式:类名() {}
a.没有返回值,也不写void
b.函数名与类名相同
c.可以有参数,可以发生重载
d.程序在调用对象的时候会自动调用构造函数,无需手动调用,而且只会调用一次
(2)析构函数 格式:~类名() {}
a.没有返回值,也不写void
b.函数名与类名相同,在名称前加~
c.不可以有参数,不可以发生重载
d.程序在对象销毁前自动调用析构,无需手动调用,而且只会调用一次
******************************************************************/
/******************************************************************
2、构造函数的分类和调用
(1)两种分类方式
a.按参数分类:有参构造函数(默认构造)和无参构造函数
b.按类型分类:普通构造函数和拷贝构造函数
(2)三种调用方式
a.括号法
b.显示法
c.隐式转换法
******************************************************************/
/******************************************************************
3、拷贝构造函数调用时机
(1)使用一个已经创建完毕的对象来初始化一个新对象
(2)值传递的方式给函数参数传值
(3)以值方式返回局部对象
******************************************************************/
/******************************************************************
4、构造函数的调用规则
默认情况下,C++编译器至少给一个类添加3个函数
(1)默认构造函数(无参,函数体为空)
(2)默认析构函数(无参,函数体为空)
(3)默认拷贝构造函数,对属性进行值拷贝
构造函数的调用规则:
(1)如果用户定义有参构造函数,C++不再提供默认无参构造,但是会提供默认拷贝构造
(2)如果用户定义拷贝构造函数,C++不再提供其他构造函数
******************************************************************/
/******************************************************************
5、深拷贝与浅拷贝
深拷贝:在堆区重新申请空间,进行拷贝操作
浅拷贝:简单地赋值拷贝操作
******************************************************************/
/******************************************************************
6、初始化列表 用于初始化属性
语法:构造函数():属性1(值1),属性2(值2)...{}
******************************************************************/
/******************************************************************
7、类对象作类成员
class A{}
class B{A a;}
当类中成员是其他类对象时,我们称该成员为 对象成员
构造顺序:先调用对象成员的构造,在调用本类构造
析构顺序与构造相反
******************************************************************/
/******************************************************************
8、静态成员
静态成员就是在成员变量和成员函数前加上关键字static,称为静态成员
静态成员分为:
(1)静态成员变量
a.所有对象共享同一份数据
b.在编译阶段分配内存
c.类内声明,类外初始化
(2)静态成员函数
a.所有对象共享同一个函数
b.静态成员函数只能访问静态成员变量
******************************************************************/
class Car
{
public:
Car() {}
Car(int a, int b, int c) :m_A(a), m_B(b), m_C(c)
{
cout << "调用Car的无参构造函数" << endl;
}
~Car()
{
cout << "调用Car的析构函数" << endl;
}
void printCar()
{
cout << "m_A=" << m_A << endl;
cout << "m_B=" << m_B << endl;
cout << "m_C=" << m_C << endl;
}
int m_A;
int m_B;
int m_C;
private:
};
class Person
{
public:
//构造函数
Person()
{
cout << "调用Person的无参构造函数" << endl;
}
Person(int a)
{
age = a;
cout << "调用Person的有参构造函数" << endl;
}
Person(int a,int height)
{
age = a;
m_Height = new int(height);//开辟在堆区,对象销毁前释放
cout << "调用Person的两个入口参数的有参构造函数" << endl;
}
//自己实现拷贝构造函数,解决浅拷贝带来的问题
Person(const Person &p)//const修饰,不能修改,
{
age = p.age;//将传入的人身上的所有属性,拷贝到我身上
//m_Height = height;编译器默认拷贝函数实现的就是这行代码
//深拷贝操作
m_Height = new int(*p.m_Height);
cout << "调用Person的拷贝构造函数" << endl;
}
~Person()
{
//析构代码,将堆区开辟数据做释放操作
if (m_Height != NULL)
{
delete m_Height;
m_Height = NULL;
}
cout << "调用Person的析构函数" << endl;
}
//静态成员函数
static void func()
{
m_A = 100;//静态成员函数可以访问静态变量,该数据共享,只有一份
//m_B = 200;//静态成员函数不可以访问非静态成员变量,无法区分到底是哪个对象的m_B
cout << "调用static void func()" << endl;
}
int age;
int * m_Height;
static int m_A;
int m_B;
Car m_Pcar;//类对象成员
private:
//静态成员函数也会有访问权限,类外不能访问
static void func2()
{
cout << "调用static void func2()" << endl;
}
};
int Person::m_A = 0;//静态成员变量类外初始化
/******************************************************************
2、构造函数的分类和调用
******************************************************************/
//构造和析构都是必须实现的,如果我们自己不提供,编译器会提供一个空实现的构造和析构
//调用
void test01()
{
//1、括号法
Person p1;//局部变量,存放在栈区,函数运行完释放(默认构造函数调用)
Person p2(10);//有参构造函数调用
Person p3(p2);//拷贝构造函数调用
//注意事项1
//调用默认构造函数,不加()
//下面这行代码,编译器会认为是一个函数的声明,不会认为在创建对象
//Person p1();
cout << "p2的年龄:" << p2.age << endl;
cout << "p3的年龄:" << p3.age << endl;
//2、显示法
Person p4 = Person(10);//有参构造
Person p5 = Person(p4);//拷贝构造
//Person(10);//匿名对象 特点:当前执行结束后,系统会立即收回匿名对象
//cout << "1111" << endl;
//注意事项2
//不要利用拷贝构造函数初始化匿名对象,编译器会认为Person(p5) === Person p5;对象声明
//Person(p5);
//3、隐式转换法
Person p6 = 10;//相当于写了 Person p4 = Person(10);有参构造
Person p7 = p6;//拷贝构造
}
/******************************************************************
3、拷贝构造函数调用时机
******************************************************************/
//(1)使用一个已经创建完毕的对象来初始化一个新对象
void test02()
{
Person p1(20);
Person p2(p1);
cout << "p2的年龄:" <<p2.age<< endl;
}
//(2)值传递的方式给函数参数传值
void doWork(Person p)
{
}
void test03()
{
Person p;
doWork(p);
}
//(3)以值方式返回局部对象
Person doWork2(void)
{
Person p1;
cout << (int *)&p1 << endl;
return p1;
}
void test04()
{
Person p = doWork2();
cout << (int *)&p << endl;
}
/******************************************************************
5、深拷贝与浅拷贝
深拷贝:在堆区重新申请空间,进行拷贝操作
浅拷贝:简单地赋值拷贝操作
******************************************************************/
void test05()
{
Person p1(18,160);
cout << "p1的年龄:" << p1.age << " p1的身高:" << *p1.m_Height << endl;
//利用编译器提供的拷贝构造函数,会做浅拷贝,
//浅拷贝带来的问题是堆区的内存重复释放
//利用深拷贝进行解决
Person p2(p1);
cout << "p2的年龄:" << p2.age << " p2的身高:" << *p2.m_Height << endl;
}
/******************************************************************
8、静态成员
静态成员就是在成员变量和成员函数前加上关键字static,称为静态成员
******************************************************************/
//有两种访问方式
void test06()
{
//通过对象访问
Person p;
p.func();
//通过类名访问
Person::func();
}
int main()
{
//test01();//调用构造函数方法
//test02();//使用一个已经创建完毕的对象来初始化一个新对象
//test03();//值传递的方式给函数参数传值
//test04();//以值方式返回局部对象
//test05();//深拷贝与浅拷贝
//Car car(1,2,3);//列表初始化
//car.printCar();
//test06();//静态成员
system("pause");
return 0;
}