Java 中构造函数调用

众所周知,在Java语言中是可以在构造函数中调用另一个构造函数的,使用this关键字即可。例如:

public class A {
    private int a;
    private int b;

    public A() {
        this(0, 0);
    }

    public A(int _a, int _b) {
        a = _a;
        b = _b;
    }

    // 其他成员
}

在Java中,通常可以使用这样的方法来减少代码量。但是,在一个构造中,只能调用一次其他的构造,否则,会在编译器报错。

C++ 中的构造函数调用

先说结论

C++ 中不能在构造函数中调用构造函数!!!C++ 中不能在构造函数中调用构造函数!!!C++ 中不能在构造函数中调用构造函数!!!(重要的事情说三遍)


首先,我写了类似于下面这样的代码,之所以没有用this是因为在C++中this表示的是指向当前对象的指针,而不是当前对象。
Point.h

#ifndef DEMO_POINT_H
#define DEMO_POINT_H
class Point {
public:
    Point();
    Point(int _x, int _y);
    void show();
    int getX() {return x;}
    int getY() {return y;}
private:
    int x;
    int y;
};
#endif //DEMO_POINT_H

Point.cpp

#include "Point.h"
#include <iostream>
using namespace std;

Point::Point() {
    Point(0, 0);
}

Point::Point(int _x, int _y) : x(_x), y(_y) {

}

void Point::show() {
    cout << "x = " << x << ", y = " << y <<endl;
}

main.cpp

int main() {
    Point p;
    p.show();
    Point p2(2,3);
    p2.show();
    return 0;
}

然而产生的结果却和预期完全不同,结果如下:
图片说明
这一看就知道,必然是内存泄露了。那么为什么会产生内存泄漏呢?
我们知道在C++中定义一个对象是要先分配内存(此时,非静态成员还未初始化),再调用构造函数(初始化非静态成员)。
在上面的代码中,定义对象 p 时,会调用类中的无参构造函数,但是无参构造函数还没有执行完,又执行了一次有参构造函数,相当于在还未创建完的p中开辟了新内存空间定义了一个匿名对象,但是,这个匿名对象初始化完成以后并不会将自己的成员变量的值赋给p,因此,p虽然定义了,但是并没有初始化成员变量。

最后一个问题

在Java中可以通过构造函数调用构造函数简化代码,那么C++ 如何简化代码量呢?
0. 构造方法定义时,在参数列表和函数体之间进行赋值。

  1. 一个构造函数如果要重用另一个构造函数的代码,可以把两个构造函数中的公共部分抽取出来定义一个私有的成员函数,然后在构造函数中调用这个成员函数即可。
  2. 如果你真的非要在一个构造函数中调用另一个构造函数,也不是不可以。必须要让第二个构造函数在第一个构造函数的内存是运行,而不能分配新的内存。使用标准库中的关键字new 和 this即可。将Point.cpp中的代码修改称如下格式即可。
#include "Point.h"
#include <iostream>
using namespace std;

Point::Point() {
    new (this)Point(0, 0);
}

Point::Point(int _x, int _y) : x(_x), y(_y) {}

void Point::show() {
    cout << "x = " << x << ", y = " << y <<endl;
}