七.构造函数的分类,调用;深拷贝与浅拷贝;初始化列表;类成员作为对象;静态成员变量与函数
1.Code
:
#include<iostream>
using namespace std;
class Person
{
public:
Person()//构造函数 初始化函数
{
cout << "Person 的构造函数调用" << endl;
}
~Person()//析构函数 清理函数
{
cout << "Person 的析构函数调用" << endl;
}
};
//一.构造函数分类:
// 1.依照参数:
// 有参/无参构造函数 (无参又被称为默认构造函数)
// 2.依照类型:
// 普通/拷贝构造函数
//注意:构造函数与类名称相同.
class Person1
{
public:
Person1()//无参构造函数
{
cout << "Person1 的无参构造函数调用" << endl;
}
Person1( int a)//有参构造函数
{
age = a;
cout << "Person1 的有参构造函数调用" << endl;
}
Person1(const Person1& p)//拷贝(复制)构造函数
{
age = p.age;
cout << "Person1 的拷贝(复制)构造函数调用" << endl;
}
~Person1()//析构函数
{
cout << "Person1 的析构函数调用" << endl;
}
public:
int age = 0;
};
//二.构造函数的调用:
// 1.调用无参构造函数
void test1()
{
Person P;
}
// 2.调用有参构造函数
void test2()
{
// 2.1. 括号法
Person1 P(10);// Person1 的有参构造函数调用
//注意1:调用无参构造函数时不能加括号,若加则编译器认为这是 一个函数声明
// 2.2. 显式法
Person1 P1 = Person1(10);// Person1 的有参构造函数调用
Person1 P2 = Person1(P1);// Person1 的拷贝(复制)构造函数调用
//Person1(10) 单独写就是匿名对象 当前行结束后,立马析构
// 2.3 隐式转换法
Person1 P3 = 10;//Person1 P3 = Person1(10);// Person1 的有参构造函数调用
Person1 P4 = P3;//Person1 P4 = Person1(P4);// Person1 的拷贝(复制)构造函数调用
//注意2:不能利用拷贝构造函数初始化匿名对象 编译器认为是对象声明
}
//三.拷贝构造函数的调用时机:
//1.使用一个已将创建完毕的对象来初始化一个新对象
void test3()
{
Person1 man(45);
//使用括号法调用有参构造函数
//对象已经创建完毕
Person1 newman1(man);
//调用拷贝构造函数
//初始化一个新对象
Person1 newman2 = man;
//拷贝构造
//初始化一个新对象
Person1 newman3;
newman3 = man;
//不是调用拷贝构造函数,而是赋值操作
}
//2.值传递的方式给函数参数传值
//相当于 Person1 P1 = P2;
void test4(Person1 P1) {}
void test5()
{
Person1 P2;//无参构造函数
test4(P2);//将无参构造函数 传递给 Person1 P1
}
//3.以值方式返回局部对象
Person1 test6()
{
Person1 P1;
cout << (int*)&P1 << endl;
return P1;
}
void test7()
{
Person1 P = test6();
cout << (int*)&P << endl;
}
//四.拷贝构造函数的调用规则:
//默认情况下,C++编译器至少给一个类添加 3 个函数:
// 1.默认构造函数 (无参,函数体为空)
// 2.默认拷贝构造函数(对属性进行拷贝)
// 3.默认析构函数(无参,函数体为空)
//构造函数调用规则如下:
// 1.若用户定义有参构造函数,则编译器不再提供
// 2.若用户定义拷贝构造函数,则编译器不再提供其它构造函数
//使用 Person1 类以作说明
//五.深拷贝与浅拷贝
// 1.深拷贝:在堆区重新申请空间,进行拷贝操作.
// 2.浅拷贝:简单的赋值拷贝操作.
class Person2
{
public:
Person2()
{
cout << "无参构造函数!" << endl;
}
Person2(int age, int height)
{
cout << "有参构造函数!" << endl;
m_age = age;
m_height = new int(height);
}
Person2(const Person2& P)
{
cout << "拷贝构造函数!" << endl;
//如果不利用深构造在堆区创建新内存,会导致浅拷贝带来的重复释放堆区问题.
m_age = P.m_age;
m_height = new int(*P.m_height);
}
~Person2()
{
cout << "析构函数!" << endl;
if(m_height != NULL)
{
delete m_height;
}
}
public:
int m_age = 0;
int* m_height = &m_age;
};
void test8()
{
Person2 P1(18,180);
Person2 P2(P1);
cout << "P1的年龄: " << P1.m_age << "身高: " << *P1.m_height << endl;
cout << "P2的年龄: " << P2.m_age << "身高: " << *P2.m_height << endl;
}
//六.初始化列表
//初始化列表语法 用来初始化属性
class Person3
{
public:
// 1. 传统方式初始化
//Person3(int a, int b, int c)
//{
// m_a = a;
// m_b = b;
// m_c = c;
//}
// 2. 初始化列表法初始化属性
Person3(int a, int b, int c) :m_a(a), m_b(b), m_c(c) {}
void display()
{
cout << " m_a = " << m_a << endl
<< " m_b = " << m_b << endl
<< " m_c = " << m_c << endl;
}
private:
int m_a;
int m_b;
int m_c;
};
//七.类成员作为对象
//注意:构造的顺序是 :先调用对象成员的构造,再调用本类构造
// 析构顺序与构造相反
class cat
{
public:
cat(string name)
{
cat_name = name;
cout << "cat 构造函数" << endl;
}
~cat()
{
cout << "cat 析构函数" << endl;
}
string cat_name;
};
class home
{
public:
home(string h_name, string c_name) :home_name(h_name),cat1(c_name)
{
cout << "home 构造函数" << endl;
}
~home()
{
cout << "home 析构函数" << endl;
}
void display()
{
cout << "名为" << cat1.cat_name << "的猫在名为 "
<< home_name << "的房子里" << endl;
}
string home_name;
cat cat1;//cat 为对象成员
};
void test9()
{
home home1("梅花", "天外");
home1.display();
}
//八.类成员函数另外一种定义方式
class Box
{
public:
double length; //长度
double breath; //宽度
double height; //高度
void set_number(double a,double b,double c);
double get_volume(void);
};
void Box::set_number(double a, double b, double c)
{
length = a;
breath = b;
height = c;
}
double Box::get_volume()
{
return length * breath * height;
}
//九.静态成员变量
//其特点:
// 1.在编译阶段分配内存
// 2.类内声明,类外初始化
// 3.所有对象共享同一份数据
//1. 声明
class Ctp
{
public:
static int as;//静态成员变量 类内声明
//static int ds = 19; //Error 类内初始化
private:
static int soon;// 类内声明
};
int Ctp::as = 12;// 类外初始化
int Ctp::soon = 13;// 类外初始化
//2.静态成员变量两种访问方式
void test10()
{
//(1)
//通过对象
Ctp Ctp1;
Ctp1.as = 100;
cout << "Ctp1.as = " << Ctp1.as << endl;
Ctp Ctp2;
Ctp2.as = 200;
cout << "Ctp1.as = " << Ctp1.as << endl;
cout << "Ctp2.as = " << Ctp2.as << endl;//共享同一份数据
//(2)
//通过类名
cout << "Ctp::as = " << Ctp::as << endl << endl;
}
//十.静态成员函数
//其特点:
//1.程序共享一个函数
//2.静态成员函数只能访问静态成员变量
class Asd
{
public:
static int a;
int b = 0;
static void func()
{
cout << "静态成员函数调用" << endl;
a = 100;
cout << "静态变量 a = " << a << endl;
//b = 190;//Error:非静态成员引用必须与特定对象相对(不可以访问非静态成员变量)
}
private:
static void func1()
{
cout << "私有权限 func1 函数调用" << endl;
}
};
int Asd::a = 19;
void test11()
{
Asd Asd1;
Asd1.func();//通过对象
Asd::func();//通过类名
}
int main()
{
cout << "1.调用无参构造函数" << endl << endl;
test1();
//在调用 Person 类函数时,系统会自动调用 Person 的构造函数以及析构函数,以完成对函数的初始化以及清除
cout << "2.调用有参构造函数" << endl << endl;
test2();
cout << "三.拷贝构造函数的调用时机:" << endl << endl;
cout << "1.使用一个已将创建完毕的对象来初始化一个新对象" << endl << endl;
test3();
cout << "2.值传递的方式给函数参数传值" << endl << endl;
test5();
cout << "3.以值方式返回局部对象" << endl << endl;
test7();
cout << "五.深拷贝与浅拷贝" << endl << endl;
test8();
cout << "六.初始化列表" << endl << endl;
Person3 P01(4,1,3);
P01.display();
cout << "七.类成员作为对象" << endl << endl;
test9();
cout << "八.类 成员函数另外一种定义方式" << endl << endl;
Box Box1;
Box1.set_number(4,3,6);
cout << "Box1.set_number(4,3,6); Box_volume = " << Box1.get_volume() << endl << endl;
cout << "九.静态成员变量" << endl << endl;
test10();
cout << "十.静态成员函数" << endl << endl;
test11();
system("pause");
return 0;
}
2.运行结果
: