内容来自小破站《黑马程序员C++》复习自用
【学习笔记】C++ 核心编程(六)类和对象——深拷贝与浅拷贝 + 列表初始化 + 静态成员
4.2 对象的初始化和清理
4.2.5 深拷贝与浅拷贝(面试经典问题)
浅拷贝:简单的复制拷贝操作
深拷贝:在堆区重新申请空间,进行拷贝操作
#include <iostream>
using namespace std;
class Person
{
public:
Person()
{
cout << "Persond的默认构造函数调用" << endl;
}
Person(int age)
{
m_Age = age;
cout << "Persond的有参构造函数调用" << endl;
}
~Person()
{
cout << "Persond的析构函数调用" << endl;
}
int m_Age;
};
void test01()
{
Person p1(18);
cout << "The age of p1 is " << p1.m_Age << endl;
}
int main() {
test01();
system("pause");
return 0;
}
下面加几行代码:
#include <iostream>
using namespace std;
class Person
{
public:
Person()
{
cout << "Persond的默认构造函数调用" << endl;
}
Person(int age, int height)
{
m_Age = age;
m_Height = new int(height);
cout << "Persond的有参构造函数调用" << endl;
}
~Person()
{
//析构代码,将堆区开辟的数据,做释放操作
if(m_Height!=NULL)
{
delete m_Height;
m_Height = NULL;
}
cout << "Persond的析构函数调用" << endl;
}
int m_Age;
int *m_Height;
};
void test01()
{
Person p1(18,180);
cout << "The age of p1 is " << p1.m_Age << "The height of p1 is " << *p1.m_Height << endl;
//用括号法创建一个对象
Person p2(p1);
cout << "The age of p2 is " << p2.m_Age << "The height of p2 is " << *p2.m_Height << endl;
}
int main() {
test01();
system("pause");
return 0;
}
出现问题:
问题分析:
解决方式:在堆区重新创建一块内存
#include <iostream>
using namespace std;
class Person
{
public:
Person()
{
cout << "Persond的默认构造函数调用" << endl;
}
Person(int age, int height)
{
m_Age = age;
m_Height = new int(height);
cout << "Persond的有参构造函数调用" << endl;
}
//要自己实现拷贝构造函数,来解决浅拷贝带来的问题
Person(const Person &p)
{
cout << "Persond的拷贝构造函数调用" << 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 << "Persond的析构函数调用" << endl;
}
int m_Age;
int *m_Height;
};
void test01()
{
Person p1(18,180);
cout << "The age of p1 is " << p1.m_Age << " The height of p1 is " << *p1.m_Height << endl;
//用括号法创建一个对象
Person p2(p1);
cout << "The age of p2 is " << p2.m_Age << " The height of p2 is " << *p2.m_Height << endl;
}
int main() {
test01();
system("pause");
return 0;
}
小结:如果属性有在堆区开辟的,一定要自己提供拷贝构造函数,防止浅拷贝带来的问题。
4.2.6 初始化列表
作用:给类中的属性进行初始化
语法:
构造函数():属性1(值1),属性2(值2)… {}
传统的初始化操作,可以利用构造函数的形式初始化,程序如下:
#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 << p.m_A + p.m_B + p.m_C << endl;
}
int main() {
test01();
system("pause");
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;
//}
Person() :m_A(10), m_B(20), m_C(30) {}
int m_A;
int m_B;
int m_C;
};
void test01()
{
Person p;
cout << p.m_A + p.m_B + p.m_C << endl;
}
int main() {
test01();
system("pause");
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(1,2,3);
cout << p.m_A + p.m_B + p.m_C << endl;
}
int main() {
test01();
system("pause");
return 0;
}
4.2.7 类对象作为类成员
C++ 类中的成员是另一个类的对象,我们称该成员为对象成员
例如:
class A {}
class B
{
A a;
}
B类中有对象A作为成员,A就成为对象成员
那么当创建B对象的时候,AB的构造与析构顺序?
#include <iostream>
using namespace std;
#include <string>
class Phone
{
public:
Phone(string pName)
{
cout << "Phone 的构造函数调用" << endl << endl;
m_PName = pName;
}
string m_PName;
};
class Person
{
public:
//默认生成了Phone m_Phone = pName(隐式转换)
Person(string name, string pName) :m_Name(name), m_Phone(pName)
{
cout << "Person 的构造函数调用" << endl << endl;
}
string m_Name;
Phone m_Phone;
};
void test01()
{
Person p("Siri", "iPhone");
cout << p.m_Name << " is using " << p.m_Phone.m_PName << endl << endl;
}
int main() {
test01();
system("pause");
return 0;
}
那么析构呢?
#include <iostream>
using namespace std;
#include <string>
class Phone
{
public:
Phone(string pName)
{
cout << "Phone 的构造函数调用" << endl << endl;
m_PName = pName;
}
~Phone()
{
cout << "Phone 的析构函数调用" << endl << endl;
}
string m_PName;
};
class Person
{
public:
//默认生成了Phone m_Phone = pName(隐式转换)
Person(string name, string pName) :m_Name(name), m_Phone(pName)
{
cout << "Person 的构造函数调用" << endl << endl;
}
string m_Name;
Phone m_Phone;
~Person()
{
cout << "Person 的析构函数调用" << endl << endl;
}
};
void test01()
{
Person p("Siri", "iPhone");
cout << p.m_Name << " is using " << p.m_Phone.m_PName << endl << endl;
}
int main() {
test01();
system("pause");
return 0;
}
即:
当其他类作为本类成员,构造的时候先构造类对象,在构造自身,析构的顺序与构造相反
构造手机——构造人——析构人——析构手机
4.2.8 静态成员
静态成员就是在成员变量和成员函数前加上关键字static,称为静态成员,静态成员分为:
- 静态成员变量
所有对象共享同一份数据。
在编译阶段分配内存。
类内声明,类外初始化 - 静态成员函数
所有对象共享同一个函数
静态成员函数只能访问静态成员变量
#include <iostream>
using namespace std;
//静态成员函数
//所有对象共享一个函数
//静态成员函数只能访问静态成员变量
class Person
{
public:
//静态成员函数
static void func()
{
m_A = 100;//静态成员函数可以访问静态的成员变量
//m_B = 100;//静态成员函数不可以访问非静态的成员变量
//无法区分到底是哪个对象的m_B属性
cout << "static void func() 的调用" << endl << endl;
}
static int m_A;//静态成员变量(特点是类内声明,类外初始化一下)
int m_B;//非静态成员变量
//静态成员函数也是有访问权限的
private:
static void func2()
{
cout << "static void func2() 的调用" << endl << endl;
}
};
int Person::m_A = 0;
//有两种访问方式
void test01()
{
//1. 通过对象进行访问
Person p;
p.func();
Person::func();
//Person::func2(); //类外访问不到私有的静态成员函数
//2. 通过类名进行访问
}
int main() {
test01();
system("pause");
return 0;
}
4.3 C++对象模型和this指针(见后续更新…)
= =
保持清醒!