• 对象初始化


    C++编译器提供的初始化方案:

    构造函数的调用方法是自动调用,也就是隐式调用,按照规则进行调用,也就是按照类名.类名()这种方式调用。

    可以通过构造函数显示的初始化类的属性

    类没有写构造函数,C++编译器会自动生成一个默认的构造函数。

    如果都设置成为显示初始化,那么当你定义一个对象数组的时候,是没有机会进行显示初始化的。

    为什么需要隐式初始化,或者是显示初始化方法的缺点?可以自动的对对象进行初始化,不用显示调用。

    copy构造函数的调用。

    赋值构造函数主要完成两个对象的赋值,用一个对象去初始化另外一个对象。

    C++编译器会自动生成一个copy构造函数,应该是浅拷贝。

    情况1:当用一个对象去初始化另外一个对象的时候,如果类中有实现的拷贝构造函数,就会调用拷贝构造函数,如果没有,就调用C++编译器自动生成的拷贝构造函数。

    情况2:一个要初始化对象,调用copy构造函数,参数为另一个类对象。

    赋值等号操作不会调用拷贝构造函数,不过可以进行操作符的重载,会调用C++编译器默认提供的等号操作。

    情况3:类对象作为实参的函数进行调用的时候,实参会初始化形参,这个时候会调用类的拷贝构造函数。

    情况4:函数的返回值是一个元素(对象,复杂类型),C++编译器会返回一个新的匿名对象,因此会调用拷贝构造函数以及析构函数,那为什么不将函数中创建的对象返回,因为这个对象是局部变量,函数调用之后就被销毁了,也就是析构了。

    既然匿名对象已经返回了,那么来接受这个匿名对象?如果不接受,那么就直接析构掉了。

    如果用一个刚刚创建的对象来接受(类名 对象名 = 函数的返回值)。这种情况,C++编译器会直接将匿名对象转换成为这个对象,相当于转正,从匿名转成有名字了。

    这样的目的是为了加快C++的速度。相当于是牺牲一个内存,这个对象就不会立马被析构了,只有等到这个新对象的生命周期的结束,才会进行析构。

    如果是创建一个对象,并且进行初始化,然后在用这个匿名对象赋值给这个初始化的对象,这个时候,这个匿名对象会被析构掉。(这个因为这个对象已经占用了内存,而上面那个例子,并没有占用内存,仅仅是将匿名对象的那个内存块给了新创建的对象。)

    调用无餐构造函数不用加括号。

    构造函数的调用规则和调用顺序:

    两个特殊的构造函数:

    当类中没有定义构造函数的时候,编译器默认提供一个无餐构造函数,并且函数体为空。

    默认拷贝函数,当类中没有定义拷贝函数的时候,编译器提供一个默认的拷贝构造函数,简单进行成员变量的值复制,也就是浅拷贝。

    构造函数调用研究:

    1:当类中没有定义任何一个构造函数的时候,C++编译器会提供默认的无参构造函数和默认拷贝构造函数

    2:当类中定义了拷贝构造函数,C++编译器不会提供无参数构造函数。

    3:当类中定义了任何非拷贝构造函数,C++编译器不提供无参构造函数。

    4:默认拷贝构造函数仅仅提供简单的赋值工作,也就是浅拷贝。

    也就是说,只要你写了构造函数,就一定要自己调用。

    构造函数总结:

    构造函数是C++中用于初始化对象状态的特殊函数

    构造函数在对象创建的时候自动被调用,这是一种回调的思想

    构造函数和普通函数都遵循重载的规则

    拷贝构造函数是对象正确初始化的重要保证

    必要的时候,必须手工编写拷贝构造函数。

    深浅拷贝和struct中的问题是一样的,都是由于不同的指针变量同时指向了同一片内存空间,其中一个将内存空间已经释放,导致其他指针变量在释放内存 空间的时候出现了问题。

    C++中对象的等号操作其实是操作符的重载,本质还是一个浅拷贝的操作。C++编译器提供的等号操作,也是一个浅拷贝操作。不过可以使用操作符的重载来解决问题。

    构造函数的初始化列表:

    在一个类里B面组合了另外一个类A,A类的构造函数带有参数,但是在定义B类的时候,需要确定应该给这个对象分配多少的内存空间,由于A类的构造函数带有参数,因此只能显示的调用,而在B类中并没有显示调用初始化,因此初始化失败。

    为此,C++提供初始化列表对类的成员变量进行初始化

    语法:

    B构造函数():A元素1初始化,A元素2初始化。。(调用对应的构造函数即可)

    构造函数的调用顺序呢?

    直行被组合对象的构造函数,如果组合对象有多个,按照定义的顺序,而不是按照初始化列表的顺序,析构函数和构造函数的调用顺序相反。(析构函数不能重载,只有构造函数和普通函数可以重载)

    如果类的属性中有一个const这么一个属性,那么需要构造函数的时候进行初始化。

    匿名对象的声明周期,如果没有对应的类对象来接替,会在被构造之后,立马析构掉。

    在构造中调用构造函数,是一件危险的行为,可能生成一个匿名对象。

    new和delete是操作符,不是函数,是C++的语法,和C语言中的malloc和free很类似。

    new操作符可以,分配基础类型变量,分配数组类型,分配类对象

    用new自动调用类写的构造函数,delete会直行类的析构函数。

    用malloc分配的内存可以用delete释放么?

    用new分配的内存可以用free释放么?

    应该可以

    new不光会分配内存,还会调用构造函数,同时可以初始化对象,

    delete对调用类的析构函数,

    static关键字修饰成员变量,成员函数,

    静态成员提供了一种同类对象的共享机制。

    成员函数可以用static修饰,就为静态成员函数。

    在静态方法中可以调用普通成员属性后者是成员方法么?不可以,因为这个类有多个对象,每个对象中的变量都可能是不相同的,因此不确定是那个对象变量的值。

    静态方法中只能使用静态成员变量。

    C++面向对象模型的初探。

    C++编译器如何管理类,对象,类和对象之间的关系的?

    C++编译器是如何管理普通成员函数和静态成员函数的?

    成员变量和成员函数的解析是分开存储的。

    普通成员变量存储于结构体里面,和struct有这相同的内存布局和字节对齐方式。

    静态成员变量存于全局数据区中

    成员函数,存储于代码段中。

    那么问题来了,有这么多对象,共用一块代码。代码是如何区分具体对象的呢?

    普通成员函数中会隐藏一个this指针,静态成员函数没有this指针,

    总结:

    C++类中的成员变量和成员函数是分开存储的。C语言的内存四区模型仍然有效。

    C++中类的普通成员函数都隐含了包含了一个指向当前对象的this指针

    静态成员函数,成员变量属于类

    静态成员函数不包含想普通成员函数一样指向自己的this指针

    类的成员函数用const来修饰,修饰的是谁?

    const写在函数的什么位置,是没有关系的,那为什么会这样的?

    const修饰的是方法中的隐藏的this指针。也就是指针指向的内存空间是不能被修改的。修饰方法的const本质是修饰this指针,由于this指针被隐藏起来了,因此可以放在任何位置

    通过添加这个const关键字,使得这个this指针变成了只读属性。

    如何返回一个引用呢?return *this这样就可以了。返回引用,就是返回自身。

    友元函数,通过设置友元函数可以在类外部对类的成员属性进行修改,这样就改变了类的封装的特性。

    友元类,常用的一种应用和java中的反射机制是类似的,目的是为了在某些时刻,直接对另外一个类中的属性变量进行修改。

    操作符的重载机制,本质是一个函数,可以用两种不同的方式来进行实现,第一种是全局函数法,为了可以直接对类的成员变量进行修改,因此,这里需要的是一个全局的友元函数。第二中方法是将这个全局函数转变成为一个类的成员方法,(这两种相互实现的方式是可以进行相关之间的转换的,区别在于使用类的成员方法中会包含一个this指针)。

    全局函数和成员函数的时候会少一个参数,这个参数就是成员函数的this指针。

  • 相关阅读:
    【java8】慎用java8的foreach循环(作废)
    【Java并发系列03】ThreadLocal详解
    【Java并发系列04】线程锁synchronized和Lock和volatile和Condition
    【Java并发系列02】Object的wait()、notify()、notifyAll()方法使用
    【Java并发系列01】Thread及ThreadGroup杂谈
    java安全管理器SecurityManager入门
    【DWR系列06】- DWR日志及js压缩
    时间插件
    springMVC中Restful支持
    面向接口编程
  • 原文地址:https://www.cnblogs.com/andyniu/p/7819730.html
Copyright © 2020-2023  润新知