美文网首页C++, C, NDK
1.干货】火爆全网的《超全C精品教程-面向对象》类(成员函数,

1.干货】火爆全网的《超全C精品教程-面向对象》类(成员函数,

作者: 鹏城十八少 | 来源:发表于2023-03-07 20:38 被阅读0次

    大纲: 

    1. 类函数

    2. 构造函数, 析构函数, 拷贝函数 

    3.友元函数

    4. 静态变量

    5. this指针

    --------------------------------------------------

    1. 类和对象

    类只是一种复杂数据类型的声明,不占用内存空间。而对象是类这种数据类型的一个变量

    类只是一张图纸,起到说明的作用,不占用内存空间;对象才是具体的零件,要有地方来存放,才会占用内存空间

    类和结构体的区别: 类里面可以放函数! 

    2. 类的创建方式

    new 关键字,new出来的是指针, 指针操作,通过箭头—>, 指针不能用.对象才能用.

    c++中,创建对象,是否要用new

    有2种创建对象的方式! 

    可以不申请new, 直接用吗?

    是的, 不new 直接用就是在栈中, 如果new就是在堆中! 

    反问: 对象岂不是没有空指针!  如果不new处理 ,不走构造函数??

    可以在堆上创建也可以在栈上创建! 

    很重要:  如果是栈,对象在方法执行完释放了, 容易调用析构函数, 同时变量会被释放! 会产生很大问题(严重)

    4. 类成员函数 

    成员函数可以声名, 成员函数也可以定义! 

    成员函数可以定义在类定义内部,或者单独使用范围解析运算符 :: 来定义,在 :: 运算符之前必须使用类名

    在类定义中定义的成员函数把函数声明为内联的,即便没有使用 inline 标识符

    类中的函数,入参数可以是Void?

    类中可以定义成员函数, 没有执行题

    need-to-insert-img

    构造函数也是函数, 所以成员函数定义, 包括构造函数

    // 成员函数定义,包括构造函数

    Line::Line( double len)

    {

        cout << "Object is being created, length = " << len << endl;

        length = len;

    }

    类.start() 访问方法的话, 要把方法的实现改成类函数才能访问的到! 

    need-to-insert-img

    12. c++中::是什么意思

    1).用于类成员函数

    2).访问静态函数

    3).用于静态变量的访问

    总的来说: ::符号是用来访问函数的! 

    例如:声明了一个类A,类A里声明了一个成员函数void f( ),但没有在类的声明里给出f的定义,那么在类外定义f时, 就要写成void A::f( ),表示这个f( )函数是类A的成员函数。

    不用 ::的话, 即使是public也不能访问到变量 

    need-to-insert-img

    5. 构造函数中如何调用构造函数?

    错误的写法, 构造函数不需要返回值

    void Box::Box(){

    }

    应该是这样.和java一样

    Box::Box(){

    }

    比如java中的自定义View

    6.析构函数(只能有一个)

    临终遗言:

    java中的临终遗言是: finalize

    析构函数(Destructor)也是一种特殊的成员函数,没有返回值,不需要程序员显式调用(程序员也没法显式调用),而是在销毁对象时自动执行

    析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源

    classBox{

    doublestate;

    friendvoidstart(Boxbox);

    public:

    doublelength;

    doublebreadth;

    doubleheight;

    voidset(doublelen,doublebre,doublehei);

    doubleget();

    Box();

    ~Box();

    };

    Box::~Box(){

    cout<<"Box"<<"Box delete:"<<endl;

    }

    Box::Box(){

    cout<<"Box"<<"Box create:"<<endl;

    }

    voidstart(Boxbox){

    cout<<"start:"<<"ss:"<<endl;

    }

    doubleBox::get(){

    returnlength*breadth*height;

    }

    voidBox::set(doublelen,doublebre,doublehei){

    length=len;

    breadth=bre;

    height=hei;

    }

    intmain(){

    Boxbox1;

    box1.length=1.0;

    box1.breadth=1.0;

    box1.height=1.0;

    box1.set(1.9,1.1,1.1);

    start(box1);

    cout<<"Box2 的体积:"<<box1.length<<endl;

    return0;

    }

    结果:  析构函数执行了2次! 

    为啥2次, 方法释放的时候调用??还是因为又产生了一个对象! 

    应该是方法执行完, 栈被释放了. 然后就调用了析构函数! 

    BoxBox create:

    start:ss:

    BoxBox delete:

    Box2 的体积:1.9

    BoxBox delete:

    分析: 用到了栈, 然后传递了对象!!

    正确写法: 不要java那种写法, 应该传递地址! 

    析构函数:如果有在对象内部开辟堆内存,可以在析构函数中释放内存

    用 new 分配内存时会调用构造函数,用 delete 释放内存时会调用析构函数()

    new 创建的对象位于堆区,通过 delete 删除时才会调用析构函数;如果没有 delete,析构函数就不会被执行。

    如果是 new 的对象,则必须调用 delete 才会调用到析构函数, 如果用了c的free会怎么样?

    malloc/free 他们是一套, new/delete 它们是一套

    malloc/free 不会去调用构造函数和析构函数

    new/delete 会调用构造函数和析构函数

    7.  拷贝构造函数 (很重要,会和析构函数相结合)

    拷贝构造函数和构造函数哪个先执行?

    调用构造函数调用拷贝构造函数并为指针 ptr 分配内存

    一个对象给另外一个对象赋值: 

    Person person1={}

    Person person2=person1;

    赋值,是把所有的属性赋值了! 原理: 调用了拷贝构造函数! 

     这个拷贝是浅拷贝,拷贝的是值

    使用场景: 

    1. 作为参数返回的时候会调用拷贝构造函数

    2. 作为参数传递的时候会调用拷贝构造函数!

    3. 一般要重写拷贝构造函数, 防止2次析构导致异常(释放)

    classLine

    {

    public:

    intgetLength(void);

    Line(intlen);// 简单的构造函数

    Line(constLine&obj);// 拷贝构造函数

    ~Line();

    3.属性私有,公有--------->想到有友元函数! 

    关键字:privite和 public

    默认情况下,类的所有成员都是私有的

    8. 友元函数---->为了访问类的私有函数或者属性 (我么是朋友, 我可以访问你)

    友元函数是不能用类::freind

    类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。

    友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。

    如果要声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字 friend

    注意: 1. 友元函数定义在类里面声明, 不要在函数的实现里面定义! 

    2. 友元函数的作用,是让你可以通过方法访问类的私有属性,而不是方法方法私有性!

    /* 因为 printWidth() 是 Box 的友元,它可以直接访问该类的任何成员 */

    所以定义的时候,这样定义

    friend void start(Box box);

    need-to-insert-img

    6.1 友元函数与普通函数的区别

    友元函数:直接方法名调用。

    普通函数:需要对象名::+方法名 调用

    友元类是: 一个类里面放另一个类的定义! 哪个类定义了友元,服务于他本身! 

    #include<iostream>

    usingnamespacestd;

    classCCar;//提前声明CCar类,以便后面的CDriver类使用

    classCDriver

    {

    public:

    voidModifyCar(CCar*pCar);//改装汽车

    };

    classCCar

    {

    private:

    intprice;

    friendintMostExpensiveCar(CCarcars[],inttotal);//声明友元

    friendvoidCDriver::ModifyCar(CCar*pCar);//声明友元

    };

    voidCDriver::ModifyCar(CCar*pCar)

    {

    pCar->price+=1000;//汽车改装后价值增加

    }

    intMostExpensiveCar(CCarcars[],inttotal)//求最贵气车的价格

    {

    inttmpMax=-1;

    for(inti=0;i<total;++i)

    if(cars[i].price>tmpMax)

    tmpMax=cars[i].price;

    returntmpMax;

    }

    intmain()

    {

    return0;

    }

    9. 静态变量和静态函数

    c++没有静态类, 但是有静态变量和静态方法! 

    内存中位置: 栈? 堆? 常量池?

    它在常量池中, 不在栈, 也不在堆中! 

    静态属性在c++中必须要出时候,初始化必须这么写, 静态成员变量必须初始化,而且只能在类体外进行! 否则报错,如下

    need-to-insert-img

       static int objectCount;

    定义初始化这么定义: 

    int Box::objectCount=10;

    而不是这样;

      static int objectCount=10;

    可是有时候我们希望在多个对象之间共享数据,对象 a 改变了某份数据后对象 b 可以检测到。

    共享数据的典型使用场景是计数,以前面的 Student 类为例,如果我们想知道班级中共有多少名学生,就可以设置一份共享的变量,每次创建对象时让该变量加 1

    我们可以使用静态成员变量来实现多个对象共享数据的目标。

    运算符 :: 来重新声明静态变量从而对它进行初始化

    类的静态成员变量为什么必须得在类外初始化?

    我的理解: 由于静态变量在编译期间必须初始化,全局变量的静态或者非静态的变量都可以赋初值0。而类中的变量要用构造函数来初始化,但是在编译期间没有创造对象,所以就没有运行构造方法。故在编译期间没有给类的静态变量初始化。所以要在类外 main之前要给该静态变量初始化,不管该静态变量的作用域为private还是public,因为编译期间private没有影响。但是一旦进入运行时,就不可以调用类中的private变量。

    static int objectCount;

    cout << "Total objects: " << Box::objectCount << endl;

    2. static 关键字

    总结:

    静态的属性定义时**必须要初始化** (实现) int Student::tag = 12;

    静态 可以直接用类名去操作 :: Student::tag += 12;

    静态的方法只能去操作静态的属性或者方法

    10.自带this指针

    this 是 const 指针,原因: 他是共享的, 它的值是不能被修改的. 

    在 C++ 中,每一个对象都能通过 this 指针来访问自己的地址。this 指针是所有成员函数的隐含参数。因此,在成员函数内部,它可以用来指向调用对象。

    不用this, 在类的内部, 也可以访问里面的变量和访问,那么为什么还要this?

    和java一样, 为了防止全局变量名和局部变量名! 

    友元函数没有 this 指针,因为友元不是类的成员。只有成员函数才有 this 指针。

    有指针, 指针访问变量或者函数可以通过 -->的方式! 

    需要对 C 结构有基本的了解,并懂得如何使用箭头 -> 运算符来访问结构成员。

    cout << "月: "<< 1 + ltm->tm_mon<< endl;

    void func()  {    

        static int val;

    }

    中,变量 val 的内存地址位于: 

    A. 已初始化数据段

    B.未初始化数据段     

    C.堆

    D.栈 

    【标准答案】B

    11. 要定义.h文件,原因是!

    12. 对象大小

    相关文章

      网友评论

        本文标题:1.干货】火爆全网的《超全C精品教程-面向对象》类(成员函数,

        本文链接:https://www.haomeiwen.com/subject/ehugldtx.html