在java里,经常可见类的构造函数调用另一个构造函数,
但是在c++里,由于构造函数允许有默认参数,使得这种需求大为减少。
虽然这样,也许偶尔我们还是希望在类的构造函数里调用另一个构造函数。
我们知道,构造一个对象时会做两件事:1,分配内存 2,执行构造函数;
所以在构造函数里调用另一个构造函数的关键是让第二个构造函数在第一次分配好的内存上执行,而不是分配新的内存,
这个可以用标准库的placement new做到:
先看看标准库中placement new的定义 inline void *__cdecl operator new(size_t, void *_P) {return (_P); }
可见没有分配新的内存。
#include class my { public: my() { new (this) my(5); } my(int i) { a=i; } int a; };
使用这个方法需要注意,如果第一个构造函数里初始化了某个成员变量,然后调用另一个构造函数,在
这个构造函数里又初始化了同一个成员变量,这样就会造成同一个成员变量初始化了两次。但
这种问题在java中也存在,编程时注意一下顺序就好了。
在C++中,一个类的构造函数没法直接调用另一个构造函数,比如:
代码块1
-
#ifndef _A_H_
-
#define _A_H_
-
#include <stdio.h>
-
#include <new>
-
class A
-
{
-
public:
-
A()
-
{
-
printf("In A::(). m_x=%d\n", m_x);
-
A(0);
-
printf("Out A::(). m_x=%d\n", m_x);
-
-
}
-
-
-
A(int x)
-
{
-
printf("In A::(int x). x=%d\n", x);
-
m_x=x;
-
}
-
-
private:
-
int m_x;
- };
这里第11行的调用A(0);只是构建了一个A的临时对象,并没有调用A(int x)来初始化自己。其运行结果是:
代码块2
-
[root@tivu25 utcov]# ./UTest.out
In A::(). m_x=4268020
In A::(int x). x=0
Out A::(). m_x=4268020
正确的方法是使用placement new:
代码块3
-
//A.h
-
#ifndef _A_H_
-
#define _A_H_
-
#include <stdio.h>
-
#include <new>
-
class A
-
{
-
public:
-
A()
-
{
-
printf("In A::(). m_x=%d\n", m_x);
-
new(this) A(0);
-
printf("Out A::(). m_x=%d\n", m_x);
-
-
}
-
-
-
A(int x)
-
{
-
printf("In A::(int x). x=%d\n", x);
-
m_x=x;
-
}
-
-
-
private:
-
int m_x;
-
};
-
- #endif
第11行应为: new(this) A(0); 也就是用当前对象来调用构造函数A(int x)构建一个“新”对象。其运行结果是:
代码4
-
[root@tivu25 utcov]# ./UTest.out
-
In A::(). m_x=4268020
-
In A::(int
x). x=0
- Out A::(). m_x=0
可以看出,当前对象确实被改变了。