private构造函数析构函数
很多情况下要求当前的程序中只有⼀个object。例如⼀个程序只有⼀个和数据库的连接,只有⼀个⿏标的object。通常我们都将构造函数的声明置于public区段,假如我们将其放⼊private区段中会发⽣什么样的后果?这意味着什么?
(1)构造函数定义private
当我们在程序中声明⼀个对象时,编译器为调⽤构造函数(如果有的话),⽽这个调⽤将通常是外部的,也就是说它不属于class对象本⾝的调⽤,假如构造函数是私有的,由于在class外部不允许访问私有成员,所以这将导致编译出错。
然⽽,对于class本⾝,可以利⽤它的static公有成员,因为它们独⽴于class对象之外,不必产⽣对象也可以使⽤它们。
此时因为构造函数被class私有化,所以我们要创建出对象,就必须能够访问到class的私有域;这⼀点只有class的成员可以做得到;但在我们建构出其对象之前,怎么能利⽤它的成员呢?static公有成员,它是独⽴于class对象⽽存在的,“我们”可以访问得到。假如在某个static函数中创建了该class的对象,并以引⽤或者指针的形式将其返回(这⾥不以对象返回,主要是构造函数是私有的,外部不能创建临时对象),就获得了这个对象的使⽤权。
下⾯是例⼦:
class OnlyHeapClass
{
public:
static OnlyHeapClass* GetInstance()
{
// 创建⼀个OnlyHeapClass对象并返回其指针
return (new OnlyHeapClass);
}
void Destroy();
private:
OnlyHeapClass() { }
~OnlyHeapClass() {}
};
int main()
{
OnlyHeapClass *p = OnlyHeapClass::GetInstance();
... // 使⽤*p
delete p;
return 0;
}
这个例⼦使⽤了私有构造函数,GetInstance()作为OnlyHeapClass的静态成员函数来在内存中创建对象:
由于要跨函数传递并且不能使⽤值传递⽅式,所以我们选择在堆上创建对象,这样即使getInstance()退出,对象也不会随之释放,可以⼿动释放。
构造函数私有化的类的设计保证了其他类不能从这个类派⽣或者创建类的实例,还有这样的⽤途:例如,实现这样⼀个class:它在内存中⾄多存在⼀个,或者指定数量个的对象(可以在class的私有域中添加⼀个static类型的计数器,它的初值置为0,然后在GetInstance()中作些限制:每次调⽤它时先检查计数器的值是否已经达到对象个数的上限值,如果是则产⽣错误,否则才new出新的对象,同时将计数器的值增1.最后,为了避免值复制时产⽣新的对象副本,除了将构造函数置为私有外,复制构造函数也要特别声明并置为私有。
如果将构造函数设计成Protected,也可以实现同样的⽬的,但是可以被继承。
(2)析构函数private
另外如何保证只能在堆上new⼀个新的类对象呢?只需把析构函数定义为私有成员。
原因是C++是⼀个静态绑定的语⾔。在编译过程中,所有的⾮虚函数调⽤都必须分析完成。即使是虚函数,也需检查可访问性。因些,当在栈上⽣成对象时,对象会⾃动析构,也就说析构函数必须可以访问。⽽堆上⽣成对象,由于析构时机由程序员控制,所以不⼀定需要析构函数。保证了不能在栈上⽣成
对象后,需要证明能在堆上⽣成它。这⾥OnlyHeapClass与⼀般对象唯⼀的区别在于它的析构函数为私有。delete操作会调⽤析构函数。所以不能编译。
析构函数的定义那么如何释放它呢?答案也很简单,提供⼀个成员函数,完成delete操作。在成员函数中,析构函数是可以访问的。当然detele操作也是可以编译通过。
void OnlyHeapClass::Destroy() {
delete this;
}
构造函数私有化的类的设计可以保证只能⽤new命令在堆中来⽣成对象,只能动态的去创建对象,这样可以⾃由的控制对象的⽣命周期。但是,这样的类需要提供创建和撤销的公共接⼝。
另外重载delete,new为私有可以达到要求对象创建于栈上的⽬的,⽤placement new也可以创建在栈上。
---------------------------------------------------------------------------------------------------------------------------------
还是不懂啊:
1.为什么要⾃⼰调⽤呢?对象结束⽣存期时不就⾃动调⽤析构函数了吗?什么情况下需要⾃⼰调⽤析构函数呢?
⽐如这样⼀种情况,你希望在析构之前必须做⼀些事情,但是⽤你类的⼈并不知道,
那么你就可以重新写⼀个函数,⾥⾯把要做的事情全部做完了再调⽤析构函数。
这样⼈家只能调⽤你这个函数析构对象,从⽽保证了析构前⼀定会做你要求的动作。
2.什么情况下才⽤得着只⽣成堆对象呢?
堆对象就是new出来的,相对于栈对象⽽⾔。什么情况下要new,什么情况下在栈⾥⾯
提前分配,⽆⾮就是何时该⽤动态,何时该⽤静态⽣成的问题。这个要根据具体情况
具体分析。⽐如你在⼀个函数⾥⾯事先知道某个对象最多只可能10个,那么你就可以
定义这个对象的⼀个数组。10个元素,每个元素都是⼀个栈对象。如果你⽆法确定数
字,那么你就可以定义⼀个这个对象的指针,需要创建的时候就new出来,并且⽤list
或者vector管理起来。
---------------------------------------------------------------------------------------------------------------------------------
类中“私有”权限的含义就是:私有成员只能在类域内被访问,不能在类域外进⾏访问。
把析构函数定义为私有的,就阻⽌了⽤户在类域外对析构函数的使⽤。这表现在如下两个⽅⾯:
1. 禁⽌⽤户对此类型的变量进⾏定义,即禁⽌在栈内存空间内创建此类型的对象。要创建对象,只能⽤ new 在堆上进⾏。
2. 禁⽌⽤户在程序中使⽤ delete 删除此类型对象。对象的删除只能在类内实现,也就是说只有类的实现者才有可能实现对对象的delete,⽤户不能随便删除对象。如果⽤户想删除对象的话,只能按照类的实现者提供的⽅法进⾏。
可见,这样做之后⼤⼤限制了⽤户对此类的使⽤。⼀般来说不要这样做;通常这样做是⽤来达到特殊的⽬的,⽐如在 singleton 的实现上。楼主可查 singleton 的资料来了解它是怎么⼀回事。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论