zoukankan      html  css  js  c++  java
  • C++——类

    1.类和结构体,只有的默认访问权限的区别

    2.类内不能定义和类外类型名相同的类型名。为什么?typedef机制?

    typedef double money;
    class Account 
    {
    private:
        typedef double money;//
    }

    3.变量名一致时的调用(不推荐相同的变量名)

    pos height;
    class Screen {
    void Screen::dummy_fcn(pos height);
    private:
      pos cursor =0 ,height=0, width=0;  
    }
    void Screen::dummy_fcn(pos height)
    {
      cursor=width*height;//传入参数  
        cursor=width*this->height;//成员
      cursor=width*Screen::height;//成员
      cursor=width*::height;//全局变量
    }

    4.初始化和赋值的区别

    class ConstRef{
    public:
        ConstRef(int ii);
    private:
      int I;
      const int ci;
      int &ri;      
    }
    ConstRef:: ConstRef(int ii){
      I=ii;
      ci=ii;//错误
      ri=i;      //错误
    }
    
    ConstRef:: ConstRef(int ii):I(ii),ci(ii), ri(i) { }//正确

    5.初始化列表的顺序与参数定义的顺序一致

    class X {
        int i;
        int j;
    public:
        X(int val):j(val),i(j){}//本想val->j->i,实际是:j->i,val->j
    }

    6.默认构造函数、委托构造函数、合成的默认构造函数

    class Sales_data{
        Sales_data(std::string s, unsigned int, double price): bookNo(s), units_sold(cnt), revenue(int*price) { }
        Sales_data():Sales_data(" ",0,0){ }//委托构造函数
     }

    6.1 三五法则

    •  三个控制类拷贝的基本操作:拷贝构造函数;赋值拷贝运算符;析构函数
    //类值的类 
    class HasPtr {
    public:
        HasPtr(const std::string &s=std::string()): ps(new std::string(s)),i(0) {}//构造函数1
        HasPtr(const HasPtr &p):ps(new std::string(*p.ps)),i(p.i){}    //构造函数2
        HasPtr &operator=(const HasPtr &);//赋值拷贝运算符
    
        ~HasPtr() { delete ps; }//此虚构函数必须同时定义一个对应的构造函数和拷贝复制运算符
    
    private:
        std::string *ps;
        int i;
    };

    需要析构函数的类也需要赋值和拷贝操作;

    需要赋值操作的类也需要拷贝操作,反之亦然;

        HasPtr f(HasPtr hp)//传值,拷贝
        {
            HasPtr ret = hp;//再拷贝
            return ret;//ret和hp都被销毁
        }
        HasPtr p("something");
        f(p);//f结束,p.ps被销毁
        HasPtr q(p);//p 和 q都指向无效内存---------------->如何解决?

    7.默认初始化、值初始化

    7.1 默认初始化

    • 不使用初值定义非静态变量 int i;
    • 类成员为类类型,使用合成的默认构造函数时?
    • 没有在构造函数中显示初始化时

    7.2 值初始化

    • 数组初始化中,提供的值数量少于数组大小
    • 不使用初始值定义局部静态变量
    • 通过T()显式求是初始化

    8.当类只含有内置类型或复合类型的成员时,编译器是不会为类合成默认构造函数的。因为:内置类型可以有自己的默认初始化,复合类型有给出的显示的构造函数进行初始化(如果没给,而复合类型中的成员又不是内置类型,说白了,找不到初始值的话,就会报错)

    8.1 B()没有给b_member初值

    8.2 去NoDefault里找初值。发现NoDefault的构造函数里也没有给初值:报错

    9.聚合类

    所有成员public,没有构造函数,没有类内初值,没有基类,没有virtual函数

    10.字面值常量类

    11.类的静态成员

    • 静态成员可以是不完全类型,可以是类本身(指针也可以,但普通数据成员不行)
    • 静态成员可以作为默认实参(因为可以提取值,但普通成员不行)

     12.析构

    • 析构函数不接受参数,不能被重载
    • 隐式销毁一个内置指针类型,不会delete它所指向的对象(智能指针会?)
    • 如果一个类需要自定义析构函数,那它也需要自定义拷贝构造函数、拷贝赋值运算符

    13.阻止拷贝-delete(不用private是因为友元可以访问)

    struct NoCopy {
        NoCopy() = default;    //使用合成的默认构造函数
        NoCopy(const NoCopy&) = delete;    //阻止拷贝//不要声明为private
        NoCopy &operator = (const NoCopy&) = delete;//阻止赋值//不要声明为private,成员函数、友元函数调用会出错
        ~NoCopy() =default;//如果是delete,就不能销毁其对象了 
    };
    • 类成员的析构函数是delete或private,则合成的析构函数将会是delete
    • ------------拷贝构造------------------------,----------拷贝构造------------------
    • ------------析构函数------------------------,----------拷贝构造------------------
    • ------------拷贝赋值运算符是delete或private或const &,----------拷贝赋值运算符----------------
    • ------------析构函数是delete或private,或有引用成员且没有类内初始化器,或有const成员且类型未显示定义默认构造函数,则合成的默认构造函数将会是delete
    • 析构函数不能是delete

    13.拷贝控制和资源管理:

    13.1 行为像值的类:有自己的状态,完全独立。

    //类值的类 
    class HasPtr {
    public:
        HasPtr(const std::string &s=std::string()): ps(new std::string(s)),i(0) {}//构造函数1
        HasPtr(const HasPtr &p):ps(new std::string(*p.ps)),i(p.i){}    //构造函数2
        HasPtr& operator=(const HasPtr &);//赋值拷贝运算符
        ~HasPtr() { delete ps; }//此虚构函数必须同时定义一个对应的构造函数和拷贝复制运算符
    private:
        std::string *ps;
        int i;
    };
    HasPtr& HasPtr::operator=(const HasPtr &rhs)
    {
        auto newp = new string(*rhs.ps);//为了避免rhs和*this是同一个对象
        delete ps;
        ps = newp;
        i = rhs.i;
        return *this;
    }

    13.2 行为像指针的类:共享状态,改变副本即改变原值。(对原值进行不同状态下的操作)

    最好的办法:shared_ptr

    直接管理资源:引用计数(存放在哪里——动态内存)

    //类指针的类 
    class HasPtr {
    public:
        HasPtr(const std::string &s=std::string()): ps(new std::string(s)),i(0),use(new std::size_t(1)) {}//构造函数1
        HasPtr(const HasPtr &p) :ps(new std::string(*p.ps)), i(p.i), use(p.use) { ++*use; }    //构造函数2
        HasPtr& operator=(const HasPtr &);//赋值拷贝运算符
    
        ~HasPtr() {
            if (--*use == 0)
            {
                delete ps;
                delete use;
            }//此虚构函数必须同时定义一个对应的构造函数和拷贝复制运算符
        }
    
    private:
        std::string *ps;
        int i;
        std::size_t *use;//引用计数
    };
    HasPtr& HasPtr::operator=(const HasPtr &rhs)
    {
        ++ *rhs.use;//增加右侧对象的引用计数
        if (--*use == 0)//先减少原本对象的引用计数(可能本来是别的对象,更改之后就要把原来的减一)
        {
            delete ps;
            delete use;
        }
        //拷贝
        ps = rhs.ps;
        i = rhs.i;
        use = rhs.use;
        return *this;
    }

    涉及资源管理的操作:构造、赋值、析构、交换(适合指针)

  • 相关阅读:
    php注册、登录界面的制作
    php将表单中数据传入到数据库
    数据操作
    Hibernate入门(五)---------事务管理
    MySQL事务(学习笔记)
    Hibernate入门(四)---------一级缓存
    Hibernate入门(三)
    反射demo(拷贝一个对象)
    反射学习小结
    Hibernate入门(二)——hibernateAPI详解
  • 原文地址:https://www.cnblogs.com/yrm1160029237/p/11469472.html
Copyright © 2011-2022 走看看