对于类
3.1 构造函数
3.1.1 控制构造函数
1.default 关键字生成默认构造函数和析构函数
default的默认构造方式可生成:默认无参数的构造函数,拷贝构造函数,赋值构造函数,析构函数同样可以由default默认构造
2.delete关键字 禁止拷贝构造 禁止赋值构造 禁止 自定义参数的构造函数 注意析构函数 不可由delete修饰
c++11以前的方式 是把需要禁止的构造函数 放在private里使外部无法调用
c++11风格的禁止构造的noncopyable基类实现如下 禁止了拷贝构造和赋值构造
class noncopyable{protected:constexpr noncopyable() = default;~noncopyable() = default;noncopyable(const noncopyable&) = delete;noncopyable& operator=(const noncopyable&) = delete;};
3.2 委托构造函数
一个构造函数,使用自己的参数,传递给其他构造函数去构造,作为自己的构造函数实现,
如下面的例子,后面两个构造函数 均传递参数 委托给第一个构造函数去实现
struct A {bool a_;char b_;int c_;float d_;double e_;A(bool a, char b, int c, float d, double e) : a_(a), b_(b), c_(c), d_(d), e_(e) {}//construct reuseA(int c) : A(true, 'b', c, 1.1, 1000.1) {}A(double e) : A(false, 'a', 0, 0.1, e) {}};int main(){A o1(10);std::cout << "a: " << o1.a_ << ", b: " << o1.b_ << ", c: " << o1.c_ << ", d: " << o1.d_ << ", e: " << o1.e_ << std::endl;A o2(5.5);std::cout << "a: " << o2.a_ << ", b: " << o2.b_ << ", c: " << o2.c_ << ", d: " << o2.d_ << ", e: " << o2.e_;getchar();return 0;}
3.3、移动构造函数:
std::move函数可以以非常简单的方式将左值引用转换为右值引用。C++ 标准库使用比如vector::push_back 等这类函数时,会对参数的对象进行复制,连数据也会复制.这就会造成对象内存的额外创建, 本来原意是想把参数push_back进去就行了,通过std::move,可以避免不必要的拷贝操作。
std::move是将对象的状态或者所有权从一个对象转移到另一个对象,只是转移,没有内存的搬迁或者内存拷贝所以可以提高利用效率,改善性能.。
对指针类型的标准库对象并不需要这么做
#include #include #include #include int main(){std::string str = "Hello";std::vector<:string> v;//调用常规的拷贝构造函数,新建字符数组,拷贝数据v.push_back(str);std::cout << "After copy, str is "" << str << """;//调用移动构造函数,掏空str,掏空后,最好不要使用strv.push_back(std::move(str));std::cout << "After move, str is "" << str << """;std::cout << "The contents of the vector are "" << v[0]<< "", "" << v[1] << """;getchar();return 0;}
3.4、override和final
作用于虚函数,更多的作用是:显式的标识是否应该多态继承或不应该。
继承:子类的虚函数多态实现要加override显式的表明,不让子类多态实现的虚函数也要记得加入final;
1、override:子类用override修饰其虚函数,表示要多态继承基类的虚函数。不可以修饰非虚函数
举一个rocksdb的merge运算符重载的例子:
class ProcessMerge : public rocksdb::MergeOperator {public: virtual bool FullMergeV2 (const MergeOperationInput &merge_in, MergeOperationOutput *merge_out) const override { merge_out->new_value.clear(); if (merge_in.existing_value != nullptr) { merge_out->new_value.assign(merge_in.existing_value->data(), merge_in.existing_value->size()); } for (const rocksdb::Slice& m : merge_in.operand_list) { merge_out->new_value.append("|"); merge_out->new_value.append(m.data(), m.size()); } return true; } const char* Name() const override { return "ProcessMerge"; }};
2、final:基类用final修饰其虚函数,以外其子类不可以多态继承该虚函数
class father { public: int a_; int GetA() {return a_;} virtual void SetA(int a) { a_ = a; LOG(INFO) << "father modify a to " << a_; } //add keyword final to avoid non-anticipated inherit in compling but not errored in running //virtual void SetA(int a) final {a_ = a;} public: father(int a):a_(a) {} }; class Son: public father { int b_; public: Son(int a, int b):father(a), b_(b) {} //add keyword override to avoid the error in compling but not errored in running.(eg. 'int SetA(double a){...} override' woule be errored by compiler) virtual void SetA(int a) override { a_ = a; LOG(INFO) << "son modify a to " << a_; } //virtual void SetA(double a) override {a_ = a;} };
如father基类的SetA实现为"virtual void SetA(int a) final {a_ = a;}",则子类Son再多态继承实现SetA方法就会报错了。
![6964f9013eff439d77660b7035219a2e.png](https://i-blog.csdnimg.cn/blog_migrate/ab3ff5956fa48534a551a4fc6023d5d3.jpeg)