当前位置: 首页> 娱乐> 明星 > 查看本分行_武汉做网站的公司怎么搜不到中企动力_江门网站建设_北京网站制作400办理多少钱

查看本分行_武汉做网站的公司怎么搜不到中企动力_江门网站建设_北京网站制作400办理多少钱

时间:2025/7/15 2:20:50来源:https://blog.csdn.net/weixin_48013375/article/details/142712179 浏览次数:0次
查看本分行_武汉做网站的公司怎么搜不到中企动力_江门网站建设_北京网站制作400办理多少钱

Effective C++中文版学习记录(二)

章节二:构造/ 析构/ 赋值运算

进度:12/55


文章目录

  • Effective C++中文版学习记录(二)
  • 条款05、了解C++默默编写并调用哪些函数
  • 条款06、若不想使用编译器自动生成的函数,就该明确拒绝
  • 条款07、为多态基类声明virtual析构函数
  • 条款08、别让异常逃离析构函数
  • 条款09、绝不在构造和析构过程中调用virtual函数
  • 条款10、令operator= 返回一个reference to *this
  • 条款11、在operator= 中处理“自我赋值”
  • 条款12、复制对象时勿忘其每一个成分


条款05、了解C++默默编写并调用哪些函数

这一步是编译器帮忙做的,当你创建一个类时,编译器会给这个类构造四个函数:

默认构造函数
拷贝构造函数
拷贝赋值操作符
析构函数

了解即可,但是要注意,编译器为类构建的默认拷贝构造函数是浅拷贝

所以当类需要完成某些拷贝功能时,建议自己重构一个深拷贝的拷贝构造函数

条款06、若不想使用编译器自动生成的函数,就该明确拒绝

这一条款的想法来源于此:

当建立了一个class如

class Father{
public:
...
};
Father Fa1, Fa2;
Father Fa3(Fa1);  // Shouldn't success
Fa1 = Fa2;        // Shouldn't success, either

我们并不希望父亲能够被拷贝,但是正如条款05,即便我们不写拷贝函数,编译器也会有个默认的拷贝

解决方法是将拷贝构造函数设置为private

class Father{
public:
...
private:Father(const Father&);Father& operator=(const Father&); 
};

这里只需要声明,不用实现,反正不会调用它。这样就能够拒绝编译器默认的拷贝功能了

条款07、为多态基类声明virtual析构函数

回顾一下virtual的用法:

C++的一大特性是多态,也就是可以通过派生类继承基类后,对基类中同名的函数进行重写,实现同名不同工的功能

class Father
{int a,b;
public:void test() { std::cout << 1 << std::endl;}
};class Son : public Father
{int c,d;
public:void test() { std::cout << 2 << std::endl;}
};

那么运行这样的代码,结果为
在这里插入图片描述
因为p1和p2都是Father类型的指针,调用test自然是会调用到Father的test

那如果想用p2调用到Son的test呢?两个方案:一是将p2变成Son类型的指针,二是将Father的test改成virtual型函数

class Father
{int a,b;
public:void virtual test() { std::cout << 1 << std::endl;}
};

这样,p2在调用test时,就会看p2指向的元素是谁,再调用它的test,此时也就是Son的test

那么回到条款07,为什么需要让基类的析构函数为virtual呢?

就如同上文的例子,Father的析构函数为non-virtual时,对p2进行析构会发生什么,实际上是调用了Father的析构函数

但是p2指向的是Son类型,它还包含了c、d两个int型变量,而Father的析构函数并不会处理c和d,因为Father本身没有c和d

这样就会造成内存泄漏问题

那么当Father的析构函数变成virtual时,p2在调用析构函数就会看p2指向的元素是谁

这样一来p2就会调用Son的析构函数,防止内存泄漏

条款08、别让异常逃离析构函数

这条很好理解,当析构时抛出异常,那么析构工作就会停止,此时的内存情况谁也没法说清楚到底是什么样的

所以当析构过程中捕捉到异常时,请设计成它会吞下异常,并继续完成析构动作,或者直接结束程序,防止不明确行为

条款09、绝不在构造和析构过程中调用virtual函数

看例子:

class A
{
public:A() {test();}~A() {test();}virtual void test() {...}
};class B: public A
{virtual void test() const override {...}
}class C: public A
{virtual void test() const override {...}
}int main()
{B p1;
}

此时,p1的构造首先是会调用基类的构造函数,即A的构造函数,但是A中有虚函数test,而p1的类型又是A的派生类B

那么理论上讲是不是会调用B的test呢?不会,因为在构造过程中virtual不会下降到派生类,那么这样就会导致一些不明确行为

析构函数同理,这是编译器规定的东西

所以解决方法就是,构造函数和析构函数里,不要有任何virtual函数的调用

条款10、令operator= 返回一个reference to *this

这条是为了满足连等号的使用,即a=b=c=10;这样的操作

class A
{
public:...A & operator=(const & a) {...; return *this;}
}

同理,+=和-=也可以这么做

条款11、在operator= 中处理“自我赋值”

这是为了防止诸如a=a的行为

解决方案是在operator=中加入判断条件

A & operator=(const & a)
{if(A == &a) return *this;...return *this;
}

条款12、复制对象时勿忘其每一个成分

情况一是字面意思,就是不要忘记任何一个成分,假如

class A
{
private:int a,b;
public:int c;   // new element
}

这里c是新加入的元素,此时就要注意之前写好的拷贝构造函数和operator=有没有处理c这个元素

情况二是基类与派生类的关系,比如用class B继承A,并且为B构建拷贝函数,那么A中的private元素可能就没法拷贝

因为没法访问到

所以考虑调用A的拷贝函数后,再针对B的额外元素进行补充

而为了保证安全,最好是构造一个init函数来实现这两个拷贝函数的共同操作部分

避免使用A的拷贝函数实现B的拷贝函数这样的操作

关键字:查看本分行_武汉做网站的公司怎么搜不到中企动力_江门网站建设_北京网站制作400办理多少钱

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: