C++的继承(五):构造函数问题

本文探讨了C++中构造函数机制可能导致的效率问题,特别是在继承链中的初始化过程。通过使用memset()和特定构造函数调用,作者展示了如何优化派生类对象的初始化,避免逐级调用基础类构造函数带来的低效。

在使用C++的过程中,运用继承来扩展基础类的时候,会不会产生额外的开销呢?会的。这是因为构造函数机制的问题。C++会机械的从顶层的基础类开始,逐级调用构造函数来初始化派生类对象。大多数情况下,这种机制正是所需要的。但是,如果初始化只需要清0呢?这样一级一级逐步清0是不是太低效了?低效,又是强制性调用,这是C++最被诟病的地方,毕竟用过C的程序员都知道,在C里面,只需要调用一个memset()就可以了。而C++程序员谁没有用过C呢?

那么构造函数能不能像虚拟析构函数那样,跳过基础类的构造函数,直接调用派生类的构造函数呢?答案是不可以!不过… …

#include <stdio.h>
#include <string.h>

class Base {
protected: Base(){}
public:
        Base(int){i=5; j=7;}
        int i;
        int j;
};

class A :public  Base {
public:
        A(int n):Base(0), n(n) {}
        A(): Base() { memset(this, 0, sizeof(A)); }
        int n;
};

int main()
{
        A a;
        printf("i,j,n = %d,%d,%d\n", a.i, a.j,a.n);
}

来看这段代码。基础类用了一个重载的受保护的空的构造函数。派生类的构造函数用这个空构造函数来“初始化”基类,实际上是走走形式,什么也没做。然后用memset()来总清。程序编译之后,空的构造函数被优化掉,从而只调用派生类的memset()。这样就避开了低效的初始化链的问题。复制构造函数和赋值也可如法炮制。

那么… …

如果含有虚函数呢,虚拟表不是被破坏了吗?这时候需要权衡,如果调用一次memset()和一次memcpy()仍然快于按部就班的逐级调用构造函数。那么这种方法还是可以用,但是要用一次默认复制构造函数来修复虚拟表。new(this) A(*this); 即通过placement new调用复制构造函数。

#include <new>

class A :public  Base {
public:
        A(int n):Base(0), n(n) {}
        A(): Base() { memset(this, 0, sizeof(A));  new(this) A(*this); }
        int n;
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值