C++ 类使用注意事项
前言 本文包含一些在使用 C++ 类时的注意事项,可避免一些常见问题,并能让你在写代码时更加自信。 因为目前我使用的是 C++ 17,所以仅保证以下内容在 C++ 17 中正确。 构造函数 对于单个参数的构造函数,推荐添加 explicit 关键字,防止隐式转换错误调用构造函数。 class DemoClass { explicit DemoClass(int test) { this->test_ = test; } } 显式声明有参构造函数后,编译器不会自动生成无参构造函数,若需要,请添加 DemoClass() = default; class DemoClass { explicit DemoClass(int test) { this->test_ = test; } DemoClass() = default; } 若子类中没有显式调用父类的构造函数,子类会默认调用父类的无参构造函数,如果父类没有无参构造函数,会报错。 析构函数 基类析构函数应该声明为 virtual,这样可以防止子类无法正确的析构。 由于基类析构函数为 virtual,派生类的析构函数应该显式的 override。 class DemoClass { virtual ~DemoClass() = default; } class ChildClass: public DemoClass { ~ChildClass() override { xxx; } } 成员变量默认值 对于类或局部作用域中未明确指定默认值的成员变量,其值遵循以下规则: 对于原生类型(primitive types),即 int、float、int*、string* 等,默认值为随机的脏数据。 对于对象(objects),例如自定义类、或 std::string 等,会调用默认(无参)构造函数,若没有默认(无参)构造函数,则报错。 对于引用(reference)类型,例如 std::string&,必须赋初始值或在构造函数中初始化,若为初始化,则报错。 float age; // 脏数据、随机值(无意义),此时访问会出现未定义行为 int *ptr; // 脏数据、随机值(无意义),此时访问会出现未定义行为 string name; // 调用默认构造函数,对于 std::string 来说为空字符串 "" DemoClass demo; // 若 DemoClass 存在无参构造函数,则调用,否则编译错误 string *pname; // 脏数据、随机值(无意义),此时访问会出现未定义行为 string &rname; // 编译错误,必须显式初始化 const string &crname; // 同上,编译错误 成员变量初始化方式 初始化成员变量一般而言有四种方式,一般而言第二种和第四种方式为等价的,不过在下面我们会看到一种例外: ...