zoukankan      html  css  js  c++  java
  • c++3(c++2的补充)

    1深拷贝和浅拷贝(编译器自带浅拷贝)

     

    其实听名字也知道,拷贝拷贝,就是复制过来,一模一样赋值,

    1. 使用一个已经创建完毕的对象来初始化一个新对象

    Person man(100); //p对象已经创建完毕
        Person newman(man); //调用拷贝构造函数

    //2. 值传递的方式给函数参数传值 //相当于Person p1 = p;

    作为参数的时候(我们知道作为参数的时候其实本质也是复制一份传递过去,所以经常发现如果没有地址符&你就算怎样改变形参参数的值,本质也不会更改)

    //3. 以值方式返回局部对象 P

    //3. 以值方式返回局部对象
    Person doWork2()
    {
        Person p1;
        cout << (int *)&p1 << endl;
        return p1;
    }
    //拷贝构造函数
        Person(const Person& p) {
            age = p.age;
            cout << "拷贝构造函数!" << endl;
        }

    所以我们就可以这样操作

    Person p2(p1);

    但是要清楚

    //如果用户提供有参构造,编译器不会提供默认构造,会提供拷贝构造
        Person p1; //此时如果用户自己没有提供默认构造,会出错
        Person p2(10); //用户提供的有参
        Person p3(p2); //此时如果用户没有提供拷贝构造,编译器会提供
    
        //如果用户提供拷贝构造,编译器不会提供其他构造函数
        Person p4; //此时如果用户自己没有提供默认构造,会出错
        Person p5(10); //此时如果用户自己没有提供有参,会出错
        Person p6(p5); //用户自己提供拷贝构造

    这是拷贝的基础知识,那么什么是深浅拷贝呢

    浅拷贝:简单的赋值拷贝操作

    深拷贝:在堆区重新申请空间,进行拷贝操作

    浅拷贝其实看上面的基础就大概差不多是浅拷贝一些应用,

    主要看看深拷贝的情况,如指针,我们知道,指针实质上就是一个局部变量在堆区,但是用指针的时候需要分配内存空间需要new这时候就在栈区了(由程序员自己控制的区)

    如下

    //拷贝构造函数  
        Person(const Person& p) {
            cout << "拷贝构造函数!" << endl;
            //如果不利用深拷贝在堆区创建新内存,会导致浅拷贝带来的重复释放堆区问题
            m_age = p.m_age;
            m_height = new int(*p.m_height);
            
        }
    
        //析构函数
        ~Person() {
            cout << "析构函数!" << endl;
            if (m_height != NULL)
            {
                delete m_height;
            }
        }
    public:
        int m_age;
        int* m_height;
    };

    如果不new一个空间深拷贝的话,那看看浅拷贝(即编译器自带的)会干嘛,本质上是:

     指针由于是拷贝,指向的地址也是一样,造成析构函数释放的时候,前面一个析构释放了,后面一个又释放

    所以这就是浅拷贝带来的问题,堆区的内存重复释放

    2 this指针

    this一般就是指所在的类,用途是

    • 当形参和成员变量同名时,可用this指针来区分
    • 在类的非静态成员函数中返回对象本身,可使用return *thiclass Person
    {
    public:
    
        Person(int age)
        {
            //1、当形参和成员变量同名时,可用this指针来区分
            this->age = age;
        }
        //返回的本体则需要引用的方式返回
        Person& PersonAddPerson(Person p)
        {
            this->age += p.age;
            //返回对象本身
        //在这里this作为值返回时因为本身就是一个指针,再加*即*this那么意义就是本体的意思了即下面的p2
    return *this; } int age; }; void test01() { Person p1(10); cout << "p1.age = " << p1.age << endl; Person p2(10); p2.PersonAddPerson(p1).PersonAddPerson(p1).PersonAddPerson(p1); cout << "p2.age = " << p2.age << endl; } int main() { test01(); system("pause"); return 0; }

     3动态多态

    这里需要一个关键字virtual

    为什么是virtual,函数前面加上virtual关键字,变成虚函数,那么编译器在编译的时候就不能确定函数调用了。

    看下面的代码

    class Animal
    {
    public:
        //Speak函数就是虚函数
        //函数前面加上virtual关键字,变成虚函数,那么编译器在编译的时候就不能确定函数调用了。
        virtual void speak()
        {
            cout << "动物在说话" << endl;
        }
    };
    
    class Cat :public Animal
    {
    public:
    !!!!!!!// 这里可加可不加virtual 结果一样!!!!!!!!!!!!!!
    void speak() { 
    cout
    << "小猫在说话" << endl;
    }
    };


    class Dog :public Animal {
    public:
      !!!!!!!// 这里可加可不加virtual 结果一样!!!!!!!!!!!!!!
    void speak() { cout << "小狗在说话" << endl; } }; //我们希望传入什么对象,那么就调用什么对象的函数 //如果函数地址在编译阶段就能确定,那么静态联编 //如果函数地址在运行阶段才能确定,就是动态联编 void DoSpeak(Animal & animal) { animal.speak(); } // //多态满足条件: //1、有继承关系 //2、子类重写父类中的虚函数 //多态使用: //父类指针或引用指向子类对象 void test01() { Cat cat; DoSpeak(cat); Dog dog; DoSpeak(dog); } int main() { test01(); system("pause"); return 0; }

    首先在c++中。。。。父类的引用或指针   。。。。。就是可以代表一家之主的意思当然可以代表这个家的地址,有了家的地址当然可以用家中的子类,父子其实就是一体。

    void DoSpeak(Animal & animal)
    DoSpeak(cat);
    DoSpeak(dog);
     

    要想让猫为参数猫说话,让狗狗说话就需要地址在编译时没有绑定,所以不加virtual的话,不管传什么都会是调用Animal的spreak结果都会是动物在说话

    所以要在编译前不绑定,即晚绑定,加virtual。那么这个原理是什么

    virtual

  • 相关阅读:
    【BZOJ1801】【AHOI2009】中国象棋(动态规划)
    【BZOJ3436】小K的农场(差分约束)
    【BZOJ2330】【SDOI2012】糖果(差分约束,SPFA)
    【BZOJ4010】【HNOI2015】菜肴制作(拓扑排序)
    【BZOJ2684】【CEOI2004】锯木厂选址(斜率优化,动态规划)
    【BZOJ1096】【ZJOI2007】仓库建设(斜率优化,动态规划)
    吞吐量(TPS)、QPS、并发数、响应时间(RT)概念
    耐得住寂寞,才能守得住繁华
    想成功,就把这九个公式背下来!
    惊人的社会定律(建议收藏!)
  • 原文地址:https://www.cnblogs.com/yangj-Blog/p/14225396.html
Copyright © 2011-2022 走看看