您当前的位置:首页 > 计算机 > 编程开发 > C语言

C构造函数的注意事项

时间:02-10来源:作者:点击数:

跟Java一样,如果类里面的成员是另一个类,则在初始化时成员类先初始化,如下:

class A {
public:
    A() {
        printf("A()\n");
    }
    ~A() {
        printf("~A()\n");
    }
};

class B {
public:
    A a; // A的构造先执行

    B() { // B的构造后执行
        printf("B()\n");
    }
    ~B() {
        printf("~B()\n");
    }
};

int main() {
    B b;
    return 0;
}

执行结果如下:

A()
B()
~B()
~A()

可以看到,B中包含A,则创建B时,A先被创建完成,然后B才能创建完成,回收时相反,B先被回收,然后再回收A。

再改一下代码:

#include <cstdio>

class A {
public:
    A() {
        printf("A()\n");
    }
    ~A() {
        printf("~A()\n");
    }
};

class B {
public:
    A a; // A的构造先执行

    B(A tempA) { // B的构造后执行
        printf("B()\n");
    }
    ~B() {
        printf("~B()\n");
    }
};

int main() {
    A a;
    B b(a);
    return 0;
}


输出结果如下:

A()
A()
B()
~A()
~B()
~A()
~A()

这里看到A只打印了两次A的构造函数调用,但是却打印了A的3次析构调用,这说明已经创建了3个A对象了,为什么构造函数只打印了两次,因为有一次是调用的拷贝构造函数,我们没写拷贝构造函数,则系统会为我们生成一个,分析如下:

  1. main函数中A a;语句让A()执行了第一次打印。
  2. main函数中B b(a);,a的参数传递,实际是调用的拷贝构造函数,所以此次没有打印。
  3. B中的A a;语句让A()执行了第二次打印。

验证一下,在A中添加拷贝构造函数,如下:

A(const A & a) {
    printf("A(const A & aReference)\n");
}

运行结果如下:

A()
A(const A & aReference)
A()
B()
~A()
~B()
~A()
~A()

main函数中B b(a);,B的构造函数如下:

B(A tempA) { 
    printf("B()\n");
}

B b(a);这里的传参操作,实际是下面的赋值语句:

A tempA(a);

所以B(A tempA)构造函数中的参数A tempA是使用拷贝构造函数创建出来的一个新对象。

我们把B构造函数再修改一下,使用初始化列表为初始化成员a,如下:

B(A tempA) : a(tempA) {
    printf("B()\n");
}

运行结果如下:

A()
A(const A & a)
A(const A & a)
B()
~A()
~B()
~A()
~A()

这时候可以看到A的两次拷贝构造。有点奇怪,按理解:main函数中A a;会调一次空构造函数,B类中的A a;也会调用一次构造函数,但是从打印结果看只调用了一次,这是因为B类中的A a;并没有走空构造函数,因为B在B的构造函数中初始化成员A aB(A tempA) : a(tempA),这里的B(A tempA)在参数传递时执行了一次A的拷贝构造函数,在调用成员列表初始化a(tempA)时,又再一次调用了A的拷贝构造函数,因为编译器知道B中的成员变量在B的构造函数中有初始化列表,所以成员声明A a;就不使用默认的空构造初始化了。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门