自定义类

默认构造函数

  • 如果我们没有显式的定义构造函数,那么编译器将会创建一个默认的构造函数;一旦我们定义了任何构造函数,那么除非我们再定义一个默认构造函数,否则该类讲没有默认构造函数;
  • 默认构造函数与自定义的构造函数似乎没有什么不同,但是实际上还是存在区别,例如类中包含有数组和指针,默认构造函数将会导致野指针等类似问题,此时需要自定义默认构造函数再内部控制对象初始化;这种情况同样可以扩大到类中,如果该类包含其它类,但是其他类没有默认构造函数,为了完成其他类的初始化,那么为该类自定义默认构造函数同样必不可少;

析构函数中的delete[ ]

  • C++中的new相当于C语言中的malloc,如果我们分配一个对象那么就用new char[], 如果要分配一组对象那么就要用new char[n];但是需要注意的是,前者可以用delete m_data, 也可以用delete [ ]释放空间,但是后者只能用delete [ ]释放空间,如果用delete释放new [ ]分配的空间,那么将会只释放第一个,从而导致内存泄漏;基于上述原因,所以我们一律使用delete[ ]在析构函数中释放分配的空间;

赋值函数

  • 赋值函数返回引用;当我们给一个值赋值时,只有返回其本身引用才有意义,否则如果返回一个新的变量,那么将会毫无意义;
  • 自我判断;赋值时无法避免把自己赋给自己,所以必须在函数内部加以判断;
  • 释放原有空间,分配新的空间 ;为什么不在原有空间上赋值,而必须销毁之前的,再创建一个新的呢?首先无法确保原有空间是否足够,其次就算足够那么我们也会浪费空间;

拷贝构造函数

  • 拷贝构造函数分浅拷贝与深拷贝:浅拷贝仅复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存,而深拷贝会另外创造一个一模一样的对象,新对象与原对象不共享内存,修改新对象不会修改原对象;如果一个类里有指针,那么则必须对该指针进行深拷贝,反之,浅拷贝即可满足条件;

运算符重载与友元函数

  • 为什么在可以使用类成员函数进行运算符重载的情况下,还要使用友元函数进行运算符重载,这是因为可能存在下列情况:A = B*2.75; 那么这个对应的是A = B.operaotr(2.75); 那么反过来呢?A=2.75*B;由于2.75并非对象,那么这种情况就无法成立,在此基础上,所以需要使用友元函数进行运算符重载;针对A=2.75*B就可以和class1 operator\(double m,const class1 &t)进行匹配;对于非成员重载运算符函数来说,运算符表达式左边的操作数对应于运算符函数的第一个参数,运算符表达式右边的操作数对应于运算符函数的第二个参数。
  • 友元函数需要注意他的作用域;如果一个友元函数在类中声明,在类外定义,那么这种情况是没有问题的;但是如果一个友元函数在类中定义呢?那么此时友元函数变成了一个内联函数,但是需要注意的是,由于此时其在外部未被声明,那么无论在类内部还是外部都不能被调用;
1
2
3
4
5
6
7
8
9
struct X{
friend void f(){}
X(f(); ) //错误:f还没有被声明
void g();
void h();
};
void X::g(){return f(); } //错误:f还没有被声明
void f();
void X:h(){return f(); } //正确,f已经被声明了

友元类

  • 友元类可以类比友元函数,一个类的友元类可以访问此类中包括非公有成员在内的所有成员;
1
2
3
class Screen{
friend class Window_mgr;
}

参考代码

0%