我觉得这两个功能属于重合了啊,都是在类调用的时候进行初始化
class T
{
public:
int a;
int b;
T();
virtual ~T();
void init();
}
T::T()
{
a = 1;
b = 2
}
void T::init()
{
a = 3;
b = 4;
}
为毛要有这种设定
大家讲道理2017-04-17 11:42:00
C++ 只规定了构造函数,init()
是用 C++ 的人自己觉得合适才需要声明的,并不是说每个 C++ 类都需要有个 init()
才行。
一般来说,构造函数应该仅用于初始化成员变量,而额外的初始化函数应该用来做业务逻辑相关的初始化,特别是包含了错误分支的业务代码。
这样规定是因为构造函数有很多限制,比如它既不能返回错误码表示错误,又不应该抛出异常(因为这样做会导致析构函数不执行,往往会造成问题),所以当业务逻辑里面存在可能失败的逻辑的时候,构造函数就无法胜任,必须再写一个单独的初始化函数来完成这些事情。
在题目中所举的例子其实是一种误用,a
/b
作为成员变量理应在构造函数里面初始化,init
如果再去初始化一次就毫无道理了,有些画蛇添足。而且构造函数写成下面这种最好:
T::T()
: a(1)
, b(2)
{}
巴扎黑2017-04-17 11:42:00
我不知道你这个类是自己设计出来为了说明问题还是从生产代码里抽象出来的。
这里我想说的问题是,RAII跟对象的两步构造。
中文我就不翻译了。
这个在c++世界中应该是经常提到的一个术语。
主要说的就是,对象创建完成时,它所需要的所有资源也都已经获得。
这个对栈上创建的对象非常有用,不需要额外的处理,对象就可以得到合适的构造;并且在对象离开它的scope时,它所获取的资源被很自然的释放。当然它要求,类的构造函数还有析构函数要好好的写。
当然,如果你有很多地方需要在栈上构造对象,那么shared_ptr是少不了的。
这个是我给它起的名字(不知道正式的名字叫啥),很多时候,这样做,也是c++中的无奈之举。
比如说,这个类在构造的时候需要创建一个数据库连接(什么?你不会自己给自己找麻烦吧)。你应该知道,在c++的构造函数里面处理一些错误/异常,是多么痛苦的事情。这个时候,把这些比较繁琐的,易于出现错误的东西拉出来,放到init函数中,是比较好的处理方法。你对init函数做错误处理也来得方便些,同时也不影响整个程序的语意。试想下,一个对象在构造函数中挂掉,你该如何对这个对象做回收呢?还是来个init函数把。
有了init,相应的,你应该做一个类似destroy的函数出来,放到析构函数里面还是让调用者自己调用,你可以自己决定。但是个人认为,还是让用户自己调比较好,万一destroy的过程中出现错误了呢?
黄舟2017-04-17 11:42:00
cpp对象定义的时候就必须初始化,不够灵活。用动态分配的话又可能忘了释放。不像java。
所以有时候构造器只是给各字段赋默认值,init才是真正的初始化,需要的时候手动调用。回收的工作由析构器来管。
不过现在不必那么纠结了,用shared_ptr吧。