explorer

万丈高楼平地起,勿在浮沙筑高台

0%

为保证多态析构的正确性,需要为基类的虚构函数加上virtual

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <string>

class BasicClass {
public:
virtual ~BasicClass() {
std::cout << "BasicClass destructor!\n";
}
};

class DerivedClass: public BasicClass {
public:
~DerivedClass() {
std::cout << "DerivedClass destructor!\n";
}
};

int main(void){

class BasicClass* p_class = new DerivedClass();

// 如果 BasicClass 的析构函数没有 virtual 关键字
// 那么执行 delete 后只会执行 BasicClass 的析构函数
// 也就是说,只释放了基类内存,而派生类的内存没有被释放掉
delete p_class;

return 0;
}
阅读全文 »

编译器默认会为一个类提供(如果它们需要被使用的话):

  • 默认构造函数:如果类编写了构造函数,则编译器就不会自动提供默认构造函数了
    • 使用 default 显示声明也可以在有其他构造函数的情况下,让编译器产生默认构造函数
  • 拷贝构造函数:没有移动函数显示定义时,拷贝函数才会被隐式的创建。其单纯地将每一个数据成员进行拷贝
    • 如果数据成员中的对象具有它自己的拷贝构造函数,则也会调用它
  • 拷贝赋值函数:单纯地将每一个数据成员进行拷贝
    • 如果数据成员中的对象具有它自己的拷贝赋值函数,则也会调用它
  • 析构函数:隐式的noexcept
  • 移动构造函数:当没有显示定义移动、拷贝、析构函数时,默认移动函数才会被隐式的创建
  • 移动赋值函数

生成的特殊函数是隐含的publicinline的,但大部分情况下都是非虚函数。 > 只有当一个类继承自基类,基类的析构函数是虚函数时,生成派生类的析构函数才也是虚函数

阅读全文 »

要养成好的习惯:永远在使用对象之前先将它初始化。 - 对于内置类型,在定义时就初始化 - 对于类类型,在构造函数初始值列表中按照声明顺序初始化 + 类类型中的私有变量是内置类型时,也可以在声明时初始化,这样可以避免初始值列表过长。 + 如果期望类类型中的对象以默认构造函数初始化时,那也可以不用放在初始值列表中

阅读全文 »