通常我们都将构造函数的声明置于
public
区段,假如我们将其放入
private
区段中会发生什么样
的后果?没错,我也知道这将会使构造函数成为私有的,这意味着什么?
我们知道,当我们在程序中声明一个对象时,编译器为调用构造函数
(
如果有的话
)
,而这个
调用将通常是外部的,也就是说它不属于
class
对象本身的调用,假如构造函数是私有的,由于
在
class
外部不允许访问私有成员,所以这将导致编译出错。
你于是说:
“哈哈。
”
我们制造了一个似乎无法产生对象的
class.
哦,
当然,
对于
class
本身,
我们还可以利用它的
static
公有成员,因为它们独立于
class
对象之外,我们不必产生对象也可
以使用它们。
嗯,
看来我们还是为带有私有构造函数的类找到了一个存在的理由。
不过我们不应
当满足于此,因为看上去应当还有发掘的余地。
首先我们来认真看一下是不是真的无法创建出一个具有私有构造函数的类对象。
“呃,
可能
未必。”你现在也许会这样说。这很好,让我们再来看看为什么,没错,因为构造函数被
class
私有化了,所以我们要创建出对象,就必须能够访问到
class
的私有域;但这一点“我们”是做
不到的,那么,谁能做得到呢?
class
的成员可以做得到;但在我们建构出其对象之前,怎么能
利用它的成员呢?噢,刚才我们刚刚提到了
static
公有成员,它是独立于
class
对象而存在的,
当然,它也是公有的,“我们”可以访问得到。假如在某个
static
函数中创建了该
class
的对象,
并以引用或者指针的形式将其返回
(
不可以以值的形式返回,想想为什么
)
,我们就获得了这个对
象的使用权。下面是例子:
class WonderfulClass
{
public:
static WonderfulClass* makeAnObject()
{
//
创建一个
WonderfulClass
对象并返回其指针
return (new WonderfulClass);
}
private:
WonderfulClass() { }
};
int main()
{
WonderfulClass *p = WonderfulClass::makeAnObject();
... //
使用
*p
delete p;
// Not neccesary here, but it's a good habit.
return 0;
}
嗯,这个例子使用了私有构造函数,但它运行得很好:
makeAnObject()
作为
WonderfulClass
的静态成员函数,
尽心尽责地为我们创建对象:
由于要跨函数传递并且不能使用值传递方式,
所
以我们选择在堆上创建对象,这样即使
makeAnObject()
退出,对象也不会随之蒸发掉,当然,使
用完之后你可不要忘了手工将它清除。
回到前面的思路:除了公有的
static
成员可以帮助我们访问私有域外,还有没有其它可以利
用的“东西”?
噢,你一定想到了使用友元,完全正确。可以使用该类的友元函数或者友元类创建其对象,
这里就不举例了。
我们知道没有人会无聊到无缘无故把一个
class
设为私有,然后再写一个和上面一模一样的
makeAnObject()
来让它的用户体验一下奇特的感觉。
我们也不太相信这只是由于
C++
的设计原因
而导致的一个“顺便的”“特殊的”“无用的”边角功能。它应当是有实际用途的。提醒一下,
到了
JAVA
中你会更容易明白很多静态方法创建对象的原理!!!
嗯,例如,我们想实现这样一个
class
:它至多只能存在一个,或者指定数量个的对象
(
还记
得标准输入输出流库中那个独一无二的
cout
吗?
)
,我们可以在
class
的私有域中添加一个
static
类型的计数器,它的初值置为
0
,然后再对
makeAnObject()
做点手脚:每次调用它时先检查计数
器的值是否已经达到对象个数的上限值,如果是则产生错误,否则才
new
出新的对象,同时将
计数器的值增
1.
最后,
为了避免值复制时产生新的对象副本,
除了将构造函数置为私有外,
复制
构造函数也要特别声明并置为私有。