一、拷贝构造函数
 1、是一种特殊的构造函数,就是用一个已有的对象去构造其同类的副本对象,即对象克隆。

 class 类名
{
类名(类名& that)
{
对类成员挨个赋值
...
}
}

练习:定义一个学生类,实现它的拷贝构造函数。
  Student stu2 = stu1; // 调用拷贝构造
  stu2 = stu1; // 调用赋值构造
 2、编译器会默认生成一个拷贝构造函数
  编译生成的拷贝构造函数默认会逐字节复制类中的每一个成员。
  如果在类A中有类B成员,会在类A的拷贝构造中自动调用类B的拷贝构造。
 3、程序员可以自定义拷贝构造来取代默认的拷贝构造。
  a、拷贝构造只能有一个,不能重载。
  b、一旦程序员自定义的拷贝构造,编译器就不再生成。
  c、在自定义的拷贝构造中能通过编码来实现成员的复制。
 
 4、一般情况下编译器生成的拷贝构造完全够用,不要轻易自定义构造。

 5、什么情况下调用拷贝构造:
  a、对象与对象赋值
  b、用对象与函数传参
  c、用对象当作返回值
 练习:已知有一个学生类

 class Student
{
char* name;
char sex;
short age;
};
Student stu1;
Student stu2 = stu1;
stu.name = new char[];

此类在使用过程中偶尔会发生段错误、数据丢失、内存泄漏,如何改进此类。

二、初始化列表
 1、是一种成员的初始化方式,在构造函数的大括号体前使用小括号对类的成员进行初始化的一种方式。

 class 类名
{
类名(参数列表):成员1(参数1),成员2(参数2)
{ }
}

a、参数列表可以解决构造函数的参数与成员重名的问题。
  b、参数列表会行于构造函数执行。
 2、如果类成员是数组,可以使用{}进行初始化。
 3、如果有成员是类,可以在初始化列表中显示调用构造函数。
 4、如果成员中有const成员、引用成员,必须使用初始化列表。
 5、类成员的构造顺序与初始化列表无关,而是与成员定义的顺序有关。

三、this指针
 1、相同类型的对象各自拥有独立的成员实例,彼此双共享一份成员函数,成员函数是如何知道谁在调用它。
 2、为了让成员函数知道是哪个对象在调用,并准确访问到对象的成员,编译器会自动为每个成员函数添加一个看不到的参数,这个参数就是指向调用对象的指针(this)。
 3、类中的所有成员函数都有this指针,包括构造、析构、拷贝构造等。
  只是构造中this指向的是正在被创建的对象。
 4、this指针默认情况下都是隐藏的(在成员函数中访问成员变量时自动就加上了),但也可以显示使用。
 5、使用情况使用this
  a、区分成员变量与参数
  b、把对象当作返回值与其它对象进行交互。
四、常对象与常函数
 1、创建对象时添加const关键字,这个对象就不可再修改,就有了常属性,就意味着整个对象中的所有东西都不能修改。
 2、常对象不能调用普通成员函数,调用成员函数就相当于把对象的this指针给了它,就会有被修改的风险。
 3、函数体前加const关键的叫常函数,常对象只能调用常函数,普通对象也可以调用常函数。
  常函数就相当于对this指针添加了cosnt属性。
 4、常函数与'非'常函数会形成重载不会冲突。
 5、如果有成员确实需要修改,它又需要被const修饰,可以对成员添加一个关键字mutable,这样即使常对象调用了常函数依然可以修改成员。
五、析构函数
 1、当对象被销毁时自动调用的函数叫析构函数,对象的整个生命周期中只能被调用一次,它是对象被销毁前的最后一个执行的动作。

class 类名
{
// 不能重载、只能有一个
// 没有返回值、没有参数
~类名(void)
{ }
}
 2、编译器会默认产生一个析构函数,默认析构函数负责销毁能看的到的成员,如果有成员是类,会自动调用成员的析构函数,成员的析构过程与构行过程相反。
 3、析构函数虽然不能与重载,但可以自定义,有自定义析构函数默认析构就不会生成。
 4、当类中有析构造函数看不到的资源时(new/malloc)、有需要还愿的设置时(把打开的文件关闭/把获取到的数据保存),这时就需要自定义析构函数。
 练习:实现一个学生类,实现其构造、拷贝构造函数,当学生对象被销毁时自动写谁的stu.txt文件中,要保证常对象也能写入。
六、赋值构造
 1、赋值构造就是一个对象给另一个对象赋值的时候调用的函数。

stu2 = stu1; // 赋值构造
Student stu2 = stu1;// 拷贝构造
void func(Student stu);// 拷贝构造
func(stu1);
Student func(void) // 拷贝构造
{
return *this;
}
Student stu = func()
 2、赋值构造函数的格式

 void operator = (Student& that)
{
}
// 可以与其它对象进行交互
Student& operator = (Student& that)
{
}
 3、编译器会默认生赋值构造,它的功能与拷贝构造的功能一样,把对象A完全拷贝给对象B。
 4、赋值构造也拷贝构造的区别
   拷贝构造:使用对象A去创建出对象B(调用时对象B还末生成)。
   赋值构造:对象A与对象B都已经构造完成,此时B = A;
   如果对象中有常成员拷贝构造可以成功调用,但赋值构造不行。
 5、一般情况下默认的赋值构造基本够用的,除非有成员是指针,指向了额外的内存空间,这种情况下才需要自定义拷贝构造、赋值构造。
 6、自定义赋值构造
  a、确定赋值构造的格式
  b、防止自赋值
   int num = 1;
   num = num;
  c、释放旧资源
  d、分配新的资源
  e、拷贝新内容
  //f、代码利用(显式调用拷贝构造)
 
七、静态成员与静态成员函数
 1、类成员被static修饰后,就会存储在bss段(此段是由编译存放的而且大小固定),在程序中动态的创建对象时它的静态成员就无法创建,所有的类对象共享一个静态成员。
 2、静态成员只能在类中声明不能类中定义(必须在类外定义)。
  类型 类名::静态成员名;
 3、静态成员就是声明在类中的全局变量,在任何位置都可以使用
  类名::静态成员名进行访问。
 4、静态成员函数,类中的成员函数被static修饰后就变成了静态成员函数,所有对象共享一份静态成员函数。
 5、静态成员函数不会传递this指针,也就不能访问成员变量。
  不通过对象也能调用静态成员函数
  类名::静态成员函数(参数)
 
八、单例模式
 1、只能创建出一个对象的类,这种类就叫作单例类,这种模式就叫作单例模式。
 2、为什么需要单例模式,是为了提高安全性和稳定性的技巧。
  只允许存在唯一对象实例
  单例模式的商业应用:
   网站计数器
   日志管理系统
   连接池、线程池、内存池
 3、获取对象实例的专门方法
  a、全局变量的定义不受控制,能防君子不能防小人
  b、专门方法是类的一部分,"我是类型我做主",
  借助类禁止在外部创建对象,仅在类内部提供获取对象的接口。
 4、如何实现单例模式
  a、禁止在类外部创建实例,私有所有的构造函数 private
  b、类自己维护其唯一实例,
   静态成员变量 static 类名 instance;
   静态成员指针 static 类名* instance;
  c、提供访问该实例的方法,静态成员函数getInstance()
 5、饿汉单例模式
  不管是否需要对象都已经创建好了。
  优点:效率高、速度快、稳定。
  缺点:浪费资源,不管需不需要对象都已经创建好;
 6、懒汉单例模式
  当首次使用获取对象时才会真正创建出对象。
  优点:节约资源
  缺点:效率低,速度慢,不安全(多线程情况下)。
 

一、操作符函数
 在C++中,编译器有能力把一个由数据、对象和操作符共同组成的表达式,解释为对一个全局或成员函数的调用。
 该全局或成员函数被称为操作符函数,通过重定义操作符函数,可以实现针对自定义类型的运算法则,并使之与内置类型一样参与各种表达式。
二、双目操作符表达式
  成员函数
    形如L#R双目操作符表达式,将被编译器解释为 L.operator#(R)
    a-b+c == a.operator-(b).operator+(c)
  全局函数
    形如L#R的双目操作符表达式,将被编译器解释为 ::operator#(L,R)
    a-(b+c) == ::operator-(a,::operator+(b,c))
 练习:把赋值运算符尝试重载为全局的。
三、单目操作符表达式
  成员函数
    形如#O或O#的单目操作表达式,将被编译器解释为 O.operator#(),唯一的操作数是调用对象。
  全局函数
    形如#O或O#的单目操作表达式,将被编译器解释为 ::operator#(O),唯一的操作数是调用对象。
四、典型的双目运算符重载

成员函数
Point operator /+-*%|^& (Point& that)
{
Point t; // 会调用无参构造
t.x = x / that.x;
t.y = y / that.y;
return t; // 不能返回局部对象的引用,否则会出现悬空引用
}
注意:原对象的值不变,要产生一个临时的对象
bool operator > < >= <= == != || && (Point& that)
{ }
Point& operator += -= *= /= (Point& that)
{ return *this;
}
注意:运算符的重载要符合情理。
 全局函数
 可能会访问到参数的私有成员:
  1、把成员变成公开,但会破坏类的封闭性。
  2、把全局函数声明为友元(友元不是成员),
  3、不能在友元函数中直接访问成员变量。

Point operator + (Point& a,Point& b)
{
Point t(a.x+b.x,a.y+b.y);
return t;
}
五、典型的单目运算符重载

成员函数:
前++/--
Point& operator ++/-- (void)
{
}
后++/--
Point operator ++/-- (int)
{
}
全局函数:
前++/--
Point& operator ++/-- (Point&)
{
}
后++/--
Point operator ++/-- (Point&,int)
{
}
六、输入、输出运算符重载
 输入、输出运算符不能重载为成员函数,只能是友元。

ostream& operator << (ostream& os,Point& p)
{
}
istream& operator >> (istream& is,Point& p)
{
}
七、特殊的运算符的重载
 [] 下标运算符,可以把对象当作数组来使用。
 () 函数运算符,可以把对象当作函数来使用。
 -> 成员访问运算符,可以把对象当作指针来使用。
 * 解引用运算符,可以把对象当作指针来使用。
 new/delete 也可以进行重载,但不建议使用。
  new会自动调用重载的new函数再构造函数。
  delete会先调用析构再调用重载的delete函数。
 只有极个别的运算符的重载对于对象来说是有意义(>>,<<)
  常考的运算符重载:前++/--,后++/--
八、运算符重载的一些限制
 1、不能重载的运算符
  :: 作用域限定符
  . 成员访问运算
  .* 成员指针解引用
  ?: 三目运算符
  sizeof 字节长度运算符
  typeid 类型信息操作符
 2、运算符的重载改变不了运算符的优先级
 3、无法改变运算符的操作个数
 4、无法发明新的运算符
 5、重载运算符要注意运算符的一致性
  不要改变运算符默认的运算规则
 6、运算符的重载是为了方便使用、增强可读,不应该成功卖弄的工具。
练习:使用C++的语法实现单向链表,并重载[]、<<。
 
 
 
 
 
 
 
 
 
 
 

C++ 类 、构造、 析构、 重载 、单例模式 学习笔记及练习的更多相关文章

  1. 第2课第1节_Java面向对象编程_类的引入_P【学习笔记】

    摘要:韦东山android视频学习笔记 1. 面向对象编程的引入,我们先写一个简单的程序输出张三,李四的名字.代码如下,假如,现在我们要在名字前面添加籍贯广东,那样岂不是每个printf语句都得修改添 ...

  2. java单例模式学习笔记

    最近一直在学习多线程,在学习过程中遇到了关于单例模式的多线程安全问题,内容如下: 一:首先什么是单例模式 单例模式具有的三要点: 一个类只能有一个实例: 必须是由它自己创建的这个实例: 它必须自行向外 ...

  3. 《C++ Primer Plus》10.3 类的构造函数和析构函数 学习笔记

    10.3.1 声明和定义构造函数构造函数原型:// constructor prototype with some default argumentsStock(const string &c ...

  4. C++类构造析构调用顺序训练(复习专用)

    //对象做函数参数 //1 研究拷贝构造 //2 研究构造函数,析构函数的调用顺序 //总结 构造和析构的调用顺序 #include "iostream" using namesp ...

  5. No2_5.类的高级特性_Java学习笔记_抽象类和成员内部类

    一.抽象类1.所谓抽象类,只声明方法的存在而不去实现它的类:2.抽象类不能被实例化,即不能实现其对象:3.abstract class 类名{ 类体 }4.包含一个或多个抽象方法的类必须声明成抽象类: ...

  6. java 单例模式学习笔记

    1.单例模式概述 单例模式就是确保类在内存中只有一个对象,该实例必须自动创建,并且对外提供. 2.优缺点 优点:在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象单例模 ...

  7. 《C++ Primer Plus》第16章 string类和标准模板库 学习笔记

    C++提供了一组功能强大的库,这些库提供了很多常见编程问题的解决方案以及简化其他问题的工具string类为将字符串作为对象来处理提供了一种方便的方法.string类提供了自动内存管理动能以及众多处理字 ...

  8. 《C++ Primer Plus》第12章 类和动态内存分配 学习笔记

    本章介绍了定义和使用类的许多重要方面.其中的一些方面是非常微妙甚至很难理解的概念.如果其中的某些概念对于您来说过于复杂,也不用害怕——这些问题对于大多数C++的初学者来说都是很难的.通常,对于诸如复制 ...

  9. 0035 Java学习笔记-注解

    什么是注解 注解可以看作类的第6大要素(成员变量.构造器.方法.代码块.内部类) 注解有点像修饰符,可以修饰一些程序要素:类.接口.变量.方法.局部变量等等 注解要和对应的配套工具(APT:Annot ...

随机推荐

  1. Chapter 3 Phenomenon——6

    A low oath made me aware that someone was with me, and the voice was impossible not to recognize. 某人 ...

  2. go语言接受者的选取

    何时使用值类型 1.如果接受者是一个 map,func 或者 chan,使用值类型(因为它们本身就是引用类型).2.如果接受者是一个 slice,并且方法不执行 reslice 操作,也不重新分配内存 ...

  3. redis集群与分片(1)-redis服务器集群、客户端分片

    下面是来自知乎大神的一段说明,个人觉得非常清晰,就收藏了. 为什么集群? 通常,为了提高网站响应速度,总是把热点数据保存在内存中而不是直接从后端数据库中读取.Redis是一个很好的Cache工具.大型 ...

  4. UUID生成随机数工具类

    package com.qiyuan.util; import java.util.UUID; public class RanNum { /** * 生成随机数<br> * GUID: ...

  5. 【eclipse修改默认注释】

    一.背景简介 丰富的注释和良好的代码规范,对于代码的阅读性和可维护性起着至关重要的作用.几乎每个公司对这的要求还是比较严格的,往往会形成自己的一套编码规范.但是再实施过程中,如果全靠手动完成,不仅效率 ...

  6. Mvc Moq HttpContext

    1: public class MockMvcHttpContext 2: { 3: public Moq.Mock<System.Web.HttpContextBase> Context ...

  7. Microsoft.AspNet.Identity 的简单使用

    要完成一个简单的注册,登陆,至少需要实现Identity中的3个接口 IUser IUserStore<TUser> : IDisposable where TUser : IUser I ...

  8. MySql社区版和企业版的区别

    1.社区版的免费,出问题MySql公司概不负责,是企业版的测试版,功能却没有企业版功能完善. 2.企业版的收费,并且价格不便宜,标准版2000美元,企业版5000美元,高级集群版10000美元(6万人 ...

  9. 从一个带有http://网络文件中获取文件名

    例如文件网址为: http://a.hiphotos.baidu.com/image/h%3D200/sign=c3da85e50123dd543e73a068e108b3df/80cb39dbb6f ...

  10. 骆驼拼写法(CamelCase)

    在英语中,依靠单词的大小写拼写复合词的做法,叫做"骆驼拼写法"(CamelCase).比如,backColor这个复合词,color的第一个字母采用大写. 这种拼写法在正规的英语中 ...