使用析构函数时清除成员变量
Member variables clearing while using destructor
我正在做一些关于 C++ 的在线测验,下面是我遇到的问题
http://www.interqiew.com/ask?ta=tqcpp01&qn=3
class A
{
public:
A(int n = 2) : m_i(n) { }
~A() { std::cout << m_i; }
protected:
int m_i;
};
class B
: public A
{
public:
B(int n) : m_a1(m_i + 1), m_a2(n) { }
public:
~B()
{
std::cout << m_i;
--m_i;
}
private:
A m_a1;
A m_a2;
};
int main()
{
{ B b(5); }
std::cout << std::endl;
return 0;
}
答案是“2531” -
我原以为答案是“21”——理由如下(似乎有误):
对象 B 使用三个起始值为 2 - 253 的成员变量创建
所以当析构函数被调用时,将以相反的顺序被删除。
对于这种情况,这里的析构函数将调用继承部分 - 我们打印 2,我们递减值并转到 1,然后在删除时打印基数 - 所以回答 21
如何打印变量 m_a2 和 m_a1 - 无法理解。
它还在基础部分(即 Class A)
中打印(值 53)
2531
是正确答案。调用析构函数的顺序总是与调用构造函数的顺序相反。
2
- B 的析构函数
5
,3
- class 字段的析构函数顺序与初始化顺序相反
1
- super class 的析构函数
参见:Order of member constructor and destructor calls
我相信每个成员对象的析构函数都在指定的析构函数之后被调用,与它们在 class 中的声明顺序相反,然后调用基对象的析构函数。
所以构建的顺序是这样的:
- 使用
m_i
2 的默认值构建基础 class A
- 构造
B
成员 m_a1
,其值基于已初始化的 m_i
- 使用参数 5
的值构造 B
成员 m_a2
并销毁如下:
- 执行
B
的析构函数体
- 毁灭
m_a2
- 毁灭
m_a1
- 摧毁基地class
A
转换为:
- 打印
m_i
- 递减
m_i
- 打印
m_a2
- 打印
m_a1
- 打印
m_i
让我们考虑构造函数
B(int n) : m_a1(m_i + 1), m_a2(n) { }
相当于
B(int n) : A(), m_a1(m_i + 1), m_a2(n) { }
所以一开始 m_i 被构造函数 A 的默认参数初始化并且等于 2。
然后m_a1会被m_i+1初始化,也就是等于3。最后m_a2等于5,调用B(5)
然后当 B 的析构函数被调用时输出
std::cout << m_i;
即
2
然后减少m_i
--m_i;
数据成员的析构函数以与其构造相反的顺序调用。所以一开始会调用m_a2的析构函数,输出
5
然后会调用m_a1的析构函数,输出
3
最后会调用基class的析构函数,输出
1
所以你会得到
2531
至于你的问题,那么 A 的析构函数被调用了三次:当 class B 的数据成员 m_a1 和 m_a2 被销毁时两次(因为它们具有类型class A) 并且当基础 class 构造函数被调用时。
我正在做一些关于 C++ 的在线测验,下面是我遇到的问题
http://www.interqiew.com/ask?ta=tqcpp01&qn=3
class A
{
public:
A(int n = 2) : m_i(n) { }
~A() { std::cout << m_i; }
protected:
int m_i;
};
class B
: public A
{
public:
B(int n) : m_a1(m_i + 1), m_a2(n) { }
public:
~B()
{
std::cout << m_i;
--m_i;
}
private:
A m_a1;
A m_a2;
};
int main()
{
{ B b(5); }
std::cout << std::endl;
return 0;
}
答案是“2531” -
我原以为答案是“21”——理由如下(似乎有误):
对象 B 使用三个起始值为 2 - 253 的成员变量创建
所以当析构函数被调用时,将以相反的顺序被删除。
对于这种情况,这里的析构函数将调用继承部分 - 我们打印 2,我们递减值并转到 1,然后在删除时打印基数 - 所以回答 21
如何打印变量 m_a2 和 m_a1 - 无法理解。 它还在基础部分(即 Class A)
中打印(值 53)2531
是正确答案。调用析构函数的顺序总是与调用构造函数的顺序相反。
2
- B 的析构函数
5
,3
- class 字段的析构函数顺序与初始化顺序相反1
- super class 的析构函数
参见:Order of member constructor and destructor calls
我相信每个成员对象的析构函数都在指定的析构函数之后被调用,与它们在 class 中的声明顺序相反,然后调用基对象的析构函数。
所以构建的顺序是这样的:
- 使用
m_i
2 的默认值构建基础 class - 构造
B
成员m_a1
,其值基于已初始化的m_i
- 使用参数 5 的值构造
A
B
成员 m_a2
并销毁如下:
- 执行
B
的析构函数体
- 毁灭
m_a2
- 毁灭
m_a1
- 摧毁基地class
A
转换为:
- 打印
m_i
- 递减
m_i
- 打印
m_a2
- 打印
m_a1
- 打印
m_i
让我们考虑构造函数
B(int n) : m_a1(m_i + 1), m_a2(n) { }
相当于
B(int n) : A(), m_a1(m_i + 1), m_a2(n) { }
所以一开始 m_i 被构造函数 A 的默认参数初始化并且等于 2。 然后m_a1会被m_i+1初始化,也就是等于3。最后m_a2等于5,调用B(5)
然后当 B 的析构函数被调用时输出
std::cout << m_i;
即
2
然后减少m_i
--m_i;
数据成员的析构函数以与其构造相反的顺序调用。所以一开始会调用m_a2的析构函数,输出
5
然后会调用m_a1的析构函数,输出
3
最后会调用基class的析构函数,输出
1
所以你会得到
2531
至于你的问题,那么 A 的析构函数被调用了三次:当 class B 的数据成员 m_a1 和 m_a2 被销毁时两次(因为它们具有类型class A) 并且当基础 class 构造函数被调用时。