5.12
1、构造函数与析构函数
#includeusing namespace std; //构造函数和析构函数默认必须有 class Person { public: //构造函数 //1、无返回值无void //2、函数名与类名相同 //3、可以有参数,可以发生重载 //4、函数调用类对象之前先调用构造函数只调一次 Person() { cout << "构造函数" << endl; } //析构函数 //1、无无 //2、函数名与类名相同,前加~ //3、无参数,不重载 //4、函数释放类对象前先析构 ~Person() { cout << "析构函数" << endl; } }; void test1() { Person p; } int main() { test1();//局部变量p函数执行完立即析构 Person p;//全局变量,执行完并不立即析构 system("pause"); return 0; }
成员私有化设置中的构造与析构函数调用
#includeusing namespace std; class Person { public: Person() { cout << "构造" << endl; } ~Person() { cout << "析构" << endl; } void setx(int x) { m_x = x; } int getx() { return m_x; } private: int m_x; }; void test1() { Person p1; p1.setx(20); cout< 构造函数的分类与调用
#includeusing namespace std; class Person { public: //无参构造 Person() { cout << "无参构造" << endl; } //有参构造 Person(int a) { cout << "有参构造" << endl; m_age = a; } //拷贝构造 Person(const Person& p) { cout << "拷贝构造" << endl; m_age = p.m_age; } ~Person() { cout << "析构" << endl; } int m_age; }; //调用 void test1() { //括号法 Person p1; Person p2(10); Person p3(p2); cout << p2.m_age << endl; cout << p3.m_age << endl; //注意事项 //无参构造括号法不加括号 //Person p1(); 编译器将之认作函数声明处理 } void test2() { //显示法 //Person p1; //Person p2 = Person(10); //Person p3 = Person(p2); //cout << p2.m_age << endl; //cout << p3.m_age << endl; //显示法中的匿名操作应用 //Person(10);匿名有参构造创建对象创建完毕后立即释放 //Person(p3);匿名拷贝构造函数创建对象,编译器将括号自动忽略,Person p3;重定义操作 } void test3() { //隐式转换法 Person p1; Person p2 = 10; Person p3 = p2; cout << p2.m_age << endl; cout << p3.m_age << endl; } int main() { test2(); system("pause"); return 0; } 拷贝构造函数的调用时机
//拷贝构造函数的调用时机 #includeusing namespace std; class Person { public: Person() { cout << "无参构造" << endl; } Person(const Person& p) { cout << "拷贝构造" << endl; m_age = p.m_age; } int m_age; }; //调用时机 void test1(Person& p) { Person p1 = p; } Person test2() { Person p1; cout << (int)&p1 << endl; return p1;//拷贝构造 //拷贝构造将函数的值返回时,先拷贝一份返回,原函数值直接释放 } int main() { //1、复制对象 //Person p1;//无参构造 //Person p2(p1);//拷贝构造 //2、值传递 //test1(p1);//拷贝构造值传递将p1复制一份传入函数 //3、返回 Person p3 = test2();//无参构造 cout << (int)&p3 << endl; system("pause"); return 0; } //构造函数的调用规则
//创建一个类,编译器默认三个构造函数,无参构造、有参构造、拷贝构造
//人为创建一个有参构造,则编译器仅保留拷贝构造
//人为创建一个拷贝构造,则编译器默认构造函数均不保留2、深浅拷贝
浅拷贝的问题所在,简单的拷贝黏贴,如果在堆区开辟一块内存,则浅拷贝后两个指针指向同一个区域,释放的时候会出现某一个重复释放的非法操作,释放按照栈区先进后出的原则
解决方法,利用深拷贝,创建两个堆区内存
#includeusing namespace std; class Person { public: Person() { cout << "无参构造" << endl; } Person(int age,int height) { m_height=new int(height); cout << "有参构造" << endl; m_age = age; } Person(const Person& p) { cout << "拷贝构造" << endl; m_age = p.m_age; //m_height = p.m_height;默认浅拷贝操作,将p的指针拷贝一份,两个指针指向相同的堆区内存 //深刻拷贝操作,堆区开辟内存,存放p的指针解引用的数据 m_height = new int(*p.m_height); } ~Person() { if (m_height != NULL) { delete m_height; m_height = NULL; } cout << "析构" << endl; } int m_age; int* m_height; }; void test1() { Person p1(10,180); cout << "p1年龄:"<< p1.m_age << "身高:" << *p1.m_height << endl; Person p2(p1); cout << "p2年龄:"<< p2.m_age << "身高:" << *p2.m_height << endl; } int main() { test1(); system("pause"); return 0; } 3、类对象作为类成员
//类对象作为类成员 #includeusing namespace std; class Phone { public: Phone() { cout << "Phone默认构造" << endl; } //Phone(string pname) //{ // m_pname = pname; // cout << "Phone有参构造" << endl; //} ~Phone() { cout << "Phone析构函数" << endl; } string m_pname; }; class Person { public: //Person(string name,string pname): m_name(name),m_p(pname)//初始化列表问题,基本格式 //{ // cout << "Person构造函数" << endl; //} //类对象作为类成员时,当不使用初始化列表的格式,要对Phone有个默认构造函数, Person(string name, string pname) { cout << "Person构造函数" << endl; m_name = name; m_p.m_pname = pname; } ~Person() { cout << "Person析构函数" << endl; } string m_name; Phone m_p; }; void test1() { Person person("张三", "apple"); cout << person.m_name << "拿着" << person.m_p.m_pname << "手机" << endl; } 但其它类对象作为本类成员时,先构造其他类对象再构造本类对象 析构的顺序与构造相反 int main() { test1(); system("pause"); return 0; } 4、静态成员变量
#includeusing namespace std; class Person { //静态成员 //1、所有对象共享 //2、类内声明类外初始化 //3、有权限 //4、两种访问方式,类名访问和类对象访问 public: static int m_age; private: static int m_height; }; int Person::m_age = 10; int Person::m_height = 180; void test1() { Person p1; cout << "p1年龄:" << p1.m_age << endl; Person p2; p2.m_age = 20;//在一个对象内将静态变量更改 cout << "p1年龄:" << p1.m_age << endl;//另一个对象里跟着更改,对象共享 } void test2() { Person p1; cout << "p1年龄:" << p1.m_age << endl;//类对象访问 cout << "p1年龄:" << Person::m_age << endl;//类名访问 } int main() { //test1(); //test2(); system("pause"); return 0; } 静态成员函数
#includeusing namespace std; class Person { //静态成员函数 public: static void func() { //静态成员函数只能访问静态成员变量 //id = 3; m_age = 30; cout << "this is func " < 这一块有个点不太清晰了,静态成员函数只能够访问静态成员变量,因为非静态成员变量不具有对象共享性
成员变量与成员函数分开存储
//成员函数和成员变量分开存储 #includeusing namespace std; class Person { public: static int m_age;//静态成员变量不属于类的对象 int m_age2;//非静态成员变量属于类的对象上,占4字节 static void func() {}//静态成员函数不属于类的对象 void func2() {}//非静态成员函数不属于类的对象上 }; void test1() { Person p1;//单个对象的字节大小为1 cout << sizeof(p1) << endl; } int main() { test1(); system("pause"); return 0; } 5、this指针
指针指向调用成员函数的对象,this指向对象,则*this可解析出该对象,返回*this即返回对象
//this指针 #includeusing namespace std; //this指针指向调用成员函数的对象,既然如此,返回对象本身可直接进行return *this class Person { public: Person(int age) { m_age = age; } Person& PersonAddAge(Person& p) { this->m_age += p.m_age; return *this;//返回p1本体,采用引用接收 //如果采用值返回的方式,则拷贝构造一个新的变量,用新变量进行调用增加函数 } int m_age; }; void test1() { Person p1(18); cout << "p1年龄:" << p1.m_age << endl; Person p2(20); //要求连续调用年龄增加函数,则使该函数返回一个p1即可,this指向p1,*this即可为p1 p1.PersonAddAge(p2).PersonAddAge(p2).PersonAddAge(p2); cout << "p1年龄:" << p1.m_age << endl; } int main() { test1(); system("pause"); return 0; } 空指针不可访问成员变量
//空指针不可访问成员变量 #includeusing namespace std; class Person { public: void showage() { if (this == NULL) { return; //保证代码的健壮性 } //this指针默认存在,指向对象表示该对象的年龄,但是该对象为空 cout << this->m_age << endl; } int m_age = 10; }; void test1() { Person* p = NULL; } int main() { test1(); system("pause"); return 0; } 常函数与常对象
//常函数与常变量 #includeusing namespace std; class Person { public: //每个成员函数内部都有一个默认的this指针,指向调用该函数的对象,且指向一定不可改变 //但是指针指向的值可以改变,如果加上一个const则限制值也不可以改变 //如果设置一个可变变量,可无视const void show() const { //m_age = 100; m_height = 188; } int m_age; mutable int m_height; }; //常对象 void test1() { const Person p;//const限制为常对象 //p.m_age = 10;常对象不可更改非可变变量的值 p.m_height = 186; p.show();//常对象只能调用常函数,因为普通函数内部可以修改变量,调用相当于侧面修改变量的值 } int main() { system("pause"); return 0; }



