我们知道,拷贝构造函数是一种特殊的构造函数,函数名称必须和类名一致,且必须有一个参数,此参数是本类型的一个引用。而为什么参数是引用传递呢?如果是值传递的话,又会调用拷贝构造函数,这样就会陷入死循环。
看下面一段代码:
#include <vector>
#include <stdio.h>
#include <stdlib.h>
class CBase
{
public:
CBase(int value): mValue(value)
{
}
~CBase()
{
}
CBase(const CBase &)
{
printf("CBase copy constructor\n");
}
private:
int mValue;
};
class CDerived: public CBase
{
public:
CDerived(int value): CBase(value), mValue(value)
{
}
~CDerived()
{
}
CDerived(CDerived const &other)
{
}
private:
int mValue;
};
int main()
{
CDerived derived(20);
std::vector<CBase> Vec;
Vec.push_back(derived);
return 0;
}
看这一段代码有什么问题吗?一开始可能看不出来,但在编译时,却出现了错误:
错误显示是在40行处没有调用匹配的基类构造函数。因为拷贝构造函数是特殊的构造函数,所以它也会先调用基类的构造函数,默认调用 CBase::CBase() 的构造函数,但因为我们已经写有自己的构造函数,所以编译器没有生成默认的 CBase::CBase() 构造函数,而我们又没有显式地调用那个带参数的基类构造函数,这样就编译失败了。要想编译通过可以:
1)在基类添加一个不带参数的构造函数
#include <vector>
#include <stdio.h>
#include <stdlib.h>
class CBase
{
public:
CBase(): mValue(0)
{
}
CBase(int value): mValue(value)
{
}
~CBase()
{
}
CBase(const CBase &)
{
printf("CBase copy constructor\n");
}
private:
int mValue;
};
class CDerived: public CBase
{
public:
CDerived(int value): CBase(value), mValue(value)
{
}
~CDerived()
{
}
CDerived(CDerived const &other)
{
}
private:
int mValue;
};
int main()
{
CDerived derived(20);
std::vector<CBase> Vec;
Vec.push_back(derived);
return 0;
}
即添加:
CBase(): mValue(0)
{
}
2)显式调用基类的构造函数:
#include <vector>
#include <stdio.h>
#include <stdlib.h>
class CBase
{
public:
CBase(int value): mValue(value)
{
}
~CBase()
{
}
CBase(const CBase &)
{
printf("CBase copy constructor\n");
}
private:
int mValue;
};
class CDerived: public CBase
{
public:
CDerived(int value): CBase(value), mValue(value)
{
}
~CDerived()
{
}
CDerived(CDerived const &other): CBase(other.mValue)
{
}
private:
int mValue;
};
int main()
{
CDerived derived(20);
std::vector<CBase> Vec;
Vec.push_back(derived);
return 0;
}
即添加:
CDerived(CDerived const &other): CBase(other.mValue)
{
}
总结:派生类的拷贝构造函数也会调用基类的构造函数,根据实际情况看是否需要写基类自己的构造函数。