文章目录
对象的构造与析构
创建一个对象时,常常需要作某些初始化的工作,例如对数据成员赋初值。注意,类的数据成员是不能在声明类时初始化的。
为了解决这个问题,C++编译器提供了构造函数(constructor)来处理对象的初始化。构造函数是一种特殊的成员函数,与其他成员函数不同,不需要用户来调用它,而是在建立对象时自动执行
1.1类的构造和解析基础
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class Test
{
public:
Test() //无参数 构造函数
{
a = 10; //作用完成对属性的初始化工作
p = (char *)malloc(100);
strcpy(p, "aaaaffff");
cout<<"我是构造函数 被执行了"<<endl;
}
void print()
{
cout<<p<<endl;
cout<<a<<endl;
}
~Test() //析构函数
{
if (p != NULL)
{
free(p);
}
cout<<"我是析构函数,被调用了" <<endl;
}
protected:
private:
int a ;
char *p;
};
//给对象搭建一个舞台,研究对象的行为
void objplay()
{
//先创建的对象 后释放
Test t1;
t1.print();
printf("分隔符\n");
Test t2;
t2.print();
}
void main11()
{
objplay();
cout<<"hello..."<<endl;
system("pause");
return ;
}
1.2类的构造和解析基础
#include <iostream>
using namespace std;
class Test2
{
public:
Test2() //无参数构造函数
{
m_a = 0;
m_b = 0;
cout<<"无参数构造函数"<<endl;
}
Test2(int a)
{
m_a = a;
m_b = 0;
}
Test2(int a, int b) //有参数构造函数 //3种方法
{
m_a = a;
m_b = b;
cout<<"有参数构造函数"<<endl;
}
//赋值构造函数 (copy构造函数) //
Test2(const Test2& obj )
{
cout<<"我也是构造函数 " <<endl;
}
public:
void printT()
{
cout<<"普通成员函数"<<endl;
}
private:
int m_a;
int m_b;
};
void main21()
{
Test2 t1; //调用无参数构造函数
cout<<"hello..."<<endl;
system("pause");
return ;
}
//调用 调用有参数构造函数 3
void main22()
{
//1括号法
Test2 t1(1, 2); //调用参数构造函数 c++编译器自动的调用构造函数
t1.printT();
// 2 =号法
Test2 t2 = (3, 4, 5, 6, 7); // = c+对等号符 功能增强 c++编译器自动的调用构造函数
Test2 t3 = 5;
//3 直接调用构造函数 手动的调用构造函数
Test2 t4 = Test2(1, 2); //匿名对象 (匿名对象的去和留) 抛砖 ....//t4对象的初始化
//
t1 = t4; //把t4 copy给 t1 //赋值操作
//对象的初始化 和 对象的赋值 是两个不同的概念
cout<<"hello..."<<endl;
system("pause");
return ;
}
1.3 显示初始化方案
#include <iostream>
using namespace std;
class Test3
{
public:
void init(int _a, int _b)
{
a = _a;
b = _b;
}
protected:
private:
int a;
int b;
};
void main31()
{
//类没有提供构造函数,c++编译器会自动给你提供一个默认的构造函数
//类没有提供构造函数 copy构造构造函数, c++编译器会自动给程序员提供一个 默认的copy构造函数 =
Test3 t1;
int a = 10;
int b = 20;
t1.init(a, b);
Test3 tArray[3];
tArray[0].init(1, 2);
tArray[1].init(1, 2);
tArray[2].init(1, 2);
//
Test3 t21; t21.init(1, 2);
Test3 t22; t22.init(1, 2);
Test3 t23; t23.init(1, 2);
//在这种场景之下 显示的初始化方案 显得很蹩脚
Test3 tArray2[3] = {t21, t22, t23};
//在这种场景之下,满足不了,编程需要
Test3 tArray3[1999] = {t21, t22, t23};
cout<<"hello..."<<endl;
system("pause");
return ;
}
1.4copy的构造函数
#include <iostream>
using namespace std;
class Test4
{
public:
Test4() //无参数构造函数
{
m_a = 0;
m_b = 0;
cout<<"无参数构造函数"<<endl;
}
Test4(int a)
{
m_a = a;
m_b = 0;
}
Test4(int a, int b) //有参数构造函数 //3种方法
{
m_a = a;
m_b = b;
cout<<"有参数构造函数"<<endl;
}
//赋值构造函数 (copy构造函数) //
Test4(const Test4& obj )
{
cout<<"我也是构造函数 " <<endl;
m_b = obj.m_b + 100;
m_a = obj.m_a + 100;
}
public:
void printT()
{
cout<<"普通成员函数"<<endl;
cout<<"m_a"<<m_a<<" m_a"<<m_b<<endl;
}
private:
int m_a;
int m_b;
};
//1 赋值构造函数 用1个对象去初始化另外一个对象
void main41()
{
Test4 t1(1, 2);
Test4 t0(1, 2);
//赋值=操作 会不会调用构造函数
//operator=()//抛砖
t0 = t1; //用t1 给 t0赋值 到操作 和 初始化是两个不同的概念
//第1种调用方法
Test4 t2 = t1; //用t1来初始化 t2
t2.printT();
cout<<"hello..."<<endl;
system("pause");
return ;
}
//第二种调用时机
void main44()
{
Test4 t1(1, 2);
Test4 t0(1, 2);
Test4 t2(t1); //用t1对象 初始化 t2对象
t2.printT();
cout<<"hello..."<<endl;
system("pause");
return ;
}
#include <iostream>
using namespace std;
class Location
{
public:
Location( int xx = 0 , int yy = 0 )
{
X = xx ; Y = yy ; cout << "Constructor Object.\n" ;
}
//copy构造函数 完成对象的初始化
Location(const Location & obj) //copy构造函数
{
X = obj.X; Y = obj.Y;
}
~Location()
{
cout << X << "," << Y << " Object destroyed." << endl ;
}
int GetX () { return X ; } int GetY () { return Y ; }
private : int X , Y ;
} ;
//业务函数 形参是一个元素
void f(Location p)
{
cout<<p.GetX()<<endl;
}
void playobj()
{
Location a(1, 2);
Location b = a;
cout<<"b对象已经初始化完毕"<<endl;
f(b); //b实参取初始化形参p,会调用copy构造函数
}
void main51()
{
playobj();
cout<<"hello..."<<endl;
system("pause");
return ;
}
#include <iostream>
using namespace std;
class Location
{
public:
Location( int xx = 0 , int yy = 0 )
{
X = xx ; Y = yy ; cout << "Constructor Object.\n" ;
}
//copy构造函数 完成对象的初始化
Location(const Location & obj) //copy构造函数
{
X = obj.X; Y = obj.Y;
}
~Location()
{
cout << X << "," << Y << " Object destroyed." << endl ;
}
int GetX () { return X ; } int GetY () { return Y ; }
private : int X , Y ;
} ;
//g函数 返回一个元素
//结论1 : 函数的返回值是一个元素 (复杂类型的), 返回的是一个新的匿名对象(所以会调用匿名对象类的copy构造函数)
//
//结论2: 有关 匿名对象的去和留
//如果用匿名对象 初始化 另外一个同类型的对象, 匿名对象 转成有名对象
//如果用匿名对象 赋值给 另外一个同类型的对象, 匿名对象 被析构
//
//你这么写代码,设计编译器的大牛们:
//我就给你返回一个新对象(没有名字 匿名对象)
Location g()
{
Location A(1, 2);
return A;
}
//
void objplay2()
{
g();
}
//
void objplay3()
{
//用匿名对象初始化m 此时c++编译器 直接把匿名对转成m;(扶正) 从匿名转成有名字了m
Location m = g();
printf("匿名对象,被扶正,不会析构掉\n");
cout<<m.GetX()<<endl;;
}
void objplay4()
{
//用匿名对象 赋值给 m2后, 匿名对象被析构
Location m2(1, 2);
m2 = g();
printf("因为用匿名对象=给m2, 匿名对象,被析构\n");
cout<<m2.GetX()<<endl;;
}
void main()
{
//objplay2();
//objplay3();
objplay4();
cout<<"hello..."<<endl;
system("pause");
return ;
}
1.5 构造函数调用规则的研究
#include <iostream>
using namespace std;
class Test
{
public:
// Test(const Test& obj) //copy构造函数 作用: 用一个对象初始化另外一个对象
// {
// a = obj.a + 100;
// b = obj.b + 100;
// }
// Test(int _a, int _b)
// {
// ;
// }
Test()
{
}
void printT()
{
cout << "a:" << a << "b: "<<b<< endl;
}
protected:
private:
int a;
int b;
};
//当类中定义了拷贝构造函数时,c++编译器不会提供无参数构造函数
//当类中定义了有参数构造函数是,c++编译器不会提供无参数构造函数
//在定义类时, 只要你写了构造函数,则必须要用
void main81()
{
//Test t1; //调用无参构造函数
cout<<"hello..."<<endl;
system("pause");
return ;
}
1.6 深拷贝与浅拷贝
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
//
class Name
{
public:
Name(const char *myp)
{
m_len = strlen(myp);
m_p =(char *) malloc(m_len + 1); //
strcpy(m_p, myp);
}
//Name obj2 = obj1;
//解决方案: 手工的编写拷贝构造函数 使用深copy
Name(const Name& obj1)
{
m_len = obj1.m_len;
m_p = (char *)malloc(m_len + 1);
strcpy(m_p, obj1.m_p);
}
~Name()
{
if (m_p != NULL)
{
free(m_p);
m_p = NULL;
m_len = 0;
}
}
protected:
private:
char *m_p ;
int m_len;
};
//对象析构的时候 出现coredump
void objplaymain()
{
Name obj1("abcdefg");
//Name obj2 = obj1; //C++编译器提供的 默认的copy构造函数 浅拷贝
Name obj3("obj3");
obj3 = obj1; // C++编译器提供的 等号操作 也属 浅拷贝
}
void main91()
{
objplaymain();
cout<<"hello..."<<endl;
system("pause");
return ;
}
1.7 构造函数初始化列表
#include <iostream>
using namespace std;
class A
{
public:
A(int _a)
{
a = _a;
cout << "构造函数" << "a" << a << endl;
}
~A()
{
cout << "析构函数" << "a" << a << endl;
}
protected:
private:
int a;
};
//1 构造函数的初始化列表 解决: 在B类中 组合了一个 A类对象 (A类设计了构造函数)
//根据构造函数的调用规则 设计A的构造函数, 必须要用;没有机会初始化A
//新的语法 Constructor::Contructor() : m1(v1), m2(v1,v2), m3(v3)
class B
{
public:
B(int _b1, int _b2) : a1(1), a2(2), c(0)
{
}
B(int _b1, int _b2, int m, int n) : a1(m), a2(n), c(0)
{
b1 = _b1;
b2 = _b2;
cout <<"B的构造函数"<<endl;
}
~B()
{
cout<<"B的析构函数" <<endl;
}
protected:
private:
int b1;
int b2;
A a2;
A a1;
const int c;
};
//2 先执行 被组合对象的构造函数
//如果组合对象有多个,按照定义顺序, 而不是按照初始化列表的顺序
//析构函数 : 和构造函数的调用顺序相反
//3 被组合对象的构造顺序 与定义顺序有关系 ,与初始化列表的顺序没有关系.
//4 初始化列表 用来 给const 属性赋值
void obj10play()
{
//A a1(10);
//B ojbB(1, 2);
//1参数传递
B ojbB2(1, 2,3, 4);
//2 调用顺序
return ;
}
void main100()
{
obj10play();
system("pause");
}
1.8 构造中调用构造
#include "iostream"
using namespace std;
//构造中调用构造是危险的行为
class MyTest
{
public:
MyTest(int a, int b, int c)
{
this->a = a;
this->b = b;
this->c = c;
}
MyTest(int a, int b)
{
this->a = a;
this->b = b;
MyTest(a, b, 100); //产生新的匿名对象
}
~MyTest()
{
printf("MyTest~:%d, %d, %d\n", a, b, c);
}
protected:
private:
int a;
int b;
int c;
public:
int getC() const { return c; }
void setC(int val) { c = val; }
};
int main()
{
MyTest t1(1, 2);
printf("c:%d", t1.getC()); //请问c的值是?
system("pause");
return 0;
}
1.9 new和delete基本用法和扩展
#include <iostream>
using namespace std;
// 1
// malloc free c语言的函数
// new delete 操作符 c++的语法
//2 new 基础类型变量 分配数组变量 分配类对象
//3
分配基础类型
void main01()
{
//
int *p = (int *)malloc(sizeof(int));
*p = 10;
//free(p);
delete p;
int *p2 = new int; //分配基础类型
*p2 = 20;
free(p2);
//
int *p3 = new int(30);
printf("*p3:%d \n", *p3);
//delete p3;
free(p3);
cout<<"hello..."<<endl;
system("pause");
return ;
}
//分配数组变量
void main02()
{
//c语言分配数组
int *p = (int *)malloc(sizeof(int) * 10); //int array[10];
p[0] = 1;
//free(p);
delete[] p;
//c++分配数组
int *pArray = new int[10] ;
pArray[1] = 2;
//delete [] pArray; //数组不要把[] 忘记
free(pArray);
char *pArray2 = new char[25] ; //char buf[25]
delete [] pArray2;
cout<<"hello..."<<endl;
system("pause");
return ;
}
class Test
{
public:
Test(int _a)
{
a = _a;
cout<<"构造函数执行" <<endl;
}
~Test()
{
cout<<"析构函数执行" <<endl;
}
protected:
private:
int a;
};
//分配对象new delete
//相同 和 不同的地方 new能执行类型构造函数 delete操作符 能执行类的析构函数
// malloc free函数 C
//1 new delete 操作符号 c++的关键字
//结论
void main()
{
//c
Test *pT1 = (Test *)malloc(sizeof(Test));
//free(pT1);
delete pT1;
//c++
Test *pT2 = new Test(10);
//delete pT2;
free(pT2);
cout<<"hello..."<<endl;
system("pause");
}
1-24 今天学到这里了,明天上午有面试,加油