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;
}

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

 

posted @ 2019-09-08 14:46  寒江小筑  阅读(149)  评论(0编辑  收藏  举报