构造函数constructions
构造函数的函数名要和class名一致!!
C++11中,当类中含有不能默认初始化的成员变量时,可以禁止默认构造函数的生成,
myClass()=delete;//表示删除默认构造函数
myClass()=default;//表示默认存在构造函数
关于构造函数的删除
有点复杂了姐妹!
- 典型的是禁止使用拷贝构造函数
- 、、、、、类似于move函数?
- 而关于delete的显式删除,并非局限于成员函数=,由此我们也知default是只局限作用于类的部分成员函数的。于是我们还可用delete来避免不必要的隐式数据类型转换。比如:
class Entity
{
public:
float X,Y;
void Init()
{
X = 0.0f;
Y = 0.0f;
}
void Print()
{
std::cout << X << "," << Y std::endl;
}
};
int main()
{
Entity e;
e.Init();
e.Print();
std::cin.get();
但是这样就意味着必须在class中要有Init函数??
在c++的槽中必须手动设置所有的初始化
或者是建立一个construction函数
只有当不写任何构造函数的时候,系统才会自动写不带形参的构造函数!
或者
Entity(float x, float y);
有了指针后
class A
{
public:
A(int m,int n)
{
v=m;
p = new int (n);
}
~A() //析构函数
{
delete p;
}
private:
int v;
int *p;
};
拷贝构造函数:copy constructors
//一般系统会提供,但是当用到指针,或者是深拷贝,需要手动写
形参为本类的对象引用,用已经有的数据对象,去构造一个新的对象,使得它们之间的类型是一样的
#include<iostream>
using namespace std;
class CExample
{
private:
int a;
public:
//构造函数
CExample(int b)
{
a=b;
printf("constructor is called\n");
}
//拷贝构造函数
CExample(const CExample & c) //必须得是引用符号!!
{
a=c.a;
printf("copy constructor is called\n");
}
//析构函数
~CExample()
{
cout<<"destructor is called\n";
}
void Show()
{
cout<<a<<endl;
}
};
int main()
{
CExample A(100);
CExample B=A;
B.Show();
return 0;
}
拷贝构造函数的调用时间:
1.当形参数是类的对象时!
#include<iostream>
using namespace std;
class CExample
{
private:
int a;
public:
CExample(int b)
{
a=b;
printf("constructor is called\n");
}
CExample(const CExample & c)
{
a=c.a;
printf("copy constructor is called\n");
}
~CExample()
{
cout<<"destructor is called\n";
}
void Show()
{
cout<<a<<endl;
}
};
void g_fun(CExample c)
{
cout<<"g_func"<<endl;
}
int main()
{
CExample A(100);
CExample B=A;
B.Show();
g_fun(A);
return 0;
}
构造函数的初始化列表
构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式。例如:
class Entity {
public:
int a;
float b;
//构造函数初始化列表
Entity(): a(0),b(8.8)
{}
//或者是构造函数内部赋值
Entity()
{
a=0;
b=8.8;
}
};
上面的俩种构造函数的方式结果都是一样的,上面的例子中两个构造函数的结果是一样的。上面的构造函数(使用初始化列表的构造函数)显式的初始化类的成员;而没使用初始化列表的构造函数是对类的成员赋值,并没有进行显式的初始化。
初始化和赋值对内置类型的成员没有什么大的区别,像上面的任一个构造函数都可以
但是对非内置类型成员变量,为了避免两次构造,推荐使用类构造函数初始化列表。但有的时候必须用带有初始化列表的构造函数:
- consrt成员或者引用类型的成员,因为const只能初始化,不能赋值
- 成员类型是没有默认构造函数的类
whole: : whole()
{
data = 0;
}
用形参,构造类的对象成员的私有成员
whole :: whole(int i,int j, int k):
two(i),one(j),data(k) //用形参k初始化了数据data
{ }
析构函数
析构函数也是一种成员函数,它的作用与构造函数完全相反
我们仅仅在主函数退出时看到析构函数被调用
析构函数就是一种在销毁对象时调用的方法,它在函数调用结束的时候才会运行哦!
析构函数的作用:
- 析构函数中调用的某些初始化代码,想要取消初始化或者销毁析构函数中的开始对象,原因是,不这样做会使内存泄漏!
- 如果在堆上手动分配了任何类型的内存,需要手动销毁!
其余的下次补充哦!