介绍所有的构造函数
1、无参构造
2、带参构造
3、拷贝构造
4、移动构造(c++11)
C++默默编写了哪些函数?
默认构造函数、拷贝构造函数、赋值运算符函数、析构函数
为什么不要在构造、析构函数中调用虚函数?
在派生类对象的基类部分构造期间,对象的类型时基类,不是派生类。对象在派生类构造函数执行前不会成为一个派生类。
同样,一旦派生类析构函数开始执行,对象内的派生类成员呈未定义值。C++视其不存在,进入基类析构函数后对象就成为一个基类对象。
析构,构造期间调用虚函数,这类调用不会下降至派生类。
C++的构造函数可以为虚函数吗?
如果构造函数是虚函数,那么就需要通过vtable 来调用,但此时面对一块 raw memeory,到哪里去找虚函数表指针呢?毕竟,虚函数表指针是在构造函数中才初始化的啊,而不是在其之前。因此构造函数不能为虚函数。
inline 是构造函数的唯一合法存储类
什么时候回用到拷贝构造函数?什么情况下要给类写拷贝构造函数?
拷贝构造函数会被调用:
- 用=定义变量时(拷贝初始化):string s = “aa”;
- 将对象作为参数传递给非引用形参
- 函数返回非引用类型对象
- 花括号初始化数组、聚合类
如果需要析构函数,则一定需要拷贝构造函数和赋值操作符
拷贝初始化和直接初始化区别:
直接初始化:
string s2(s1);
string s2(“aa”);
直接初始化,使用函数匹配选择最匹配的构造函数
拷贝初始化:
string s = s1;
string s = “aa”;
拷贝初始化使用拷贝构造函数
必须使用初始化列表的几种情况?
- 类的成员变量有const修饰; (C++11还可以类内初始化)
- 类的成员为引用;
- 类的成员为没有默认构造函数的类类型;
- 如果类存在继承关系,派生类必须在其初始化列表中调用基类的构造函数;
什么情况下声明虚析构函数?
为多态性质的基类声明虚析构函数:
继承类对象经由一个基类指针被删除,若基类是非虚的析构函数,继承类的成分没有被销毁,造成局部销毁对象,形成资源泄漏,败坏数据结构。
构造顺序
虚派生中,虚基类由最底层的派生类初始化:最底层派生类的构造函数独自控制虚基类的初始化过程。
含有虚基类的对象的构造顺序与一般的顺序不同:首先使用提供给最底层派生类构造函数的初始值初始化该对象虚基类子部分,接下来按照直接基类在派生列表中出现的次序依次对其进行初始化。
虚基类总是先于非虚基类构造,与它们在继承体系中的次序位置无关。
析构函数中抛出异常会出现什么情况?
当某个异常发生,析构函数被调用,析构函数又抛出异常,两个异常同时存在情况下,程序不是结束执行,就是导致不明确行为
手写赋值运算符函数
- 先定义swap函数
- 再在赋值运算符中使用swap函数(CAS:copy-and-swap)
顺便提一下swap函数(effective 条款25):提供一个成员swap,以及一个非成员swap用来调用前者。
using namespace std;
class myclass
{
public:
myclass(int p_) :p(p_){};
void swap(myclass& lhs)
{
using std::swap;
swap(p, lhs.p);
}
myclass & operator = (myclass& lhs)
{
myclass tmp(lhs);
swap(tmp);
return *this;
}
private:
int p;
};
void swap(myclass& lhs, myclass& rhs)
{
lhs.swap(rhs);
}
int main()
{
myclass a(0), b(1);
swap(a, b);
b = a;
return 0;
}