【2016/3】C++ 类与对象进阶 运算符重载 new delete 模板 继承

类与对象:

const常量哪怕栈空间数据被改 被访问时依然是使用存于符号表的数据

构造函数的形式:
拷贝构造 Test(Test &t){}
初始化构造 Test(int d): data(d){}

   Test t(10);
   t = 200;    
   //只要类型不同,会创建一个中间的无名变量来赋值;
   //实际上是调用了构造函数中的 Test(200) 创建了一个对象,将对象赋值给t;
   //如果构造函数中使用explicit作为修饰,不能隐式转化时,会杜绝这种情况发生;
   //上一行的情况则必须 使用:   t = (Test) 200;

   Test t1 = t2;       //拷贝构造
   Test t1; t1 = t2;   //运算符重载赋值

拷贝构造: 形如 void fun(Test a);
如果函数的参数是以传入对象的形式, 那么传入对象的时候会进行一次拷贝构造

     返回值是对象的时候: Test fun(int a)
                         {
                             Test new_one(a);
                             return new_one;
                         }
如果编译器做了优化 可能会延长返回对象的生存周期 而不是重新拷贝构造一个无名对象来返回

*拷贝构造的时候要考虑浅拷贝和深拷贝的问题

         注意: 局部对象不能以引用形式返回,局部对象会被销毁

*拷贝构造的参数最好使用const修饰 比如Test(const Test &t)(…)
因为return的时候可能会检测到拷贝构造函数,而return返回的对象具有常性,需要const属性

赋值函数的编写:
1.自身赋值问题
2.释放原有内存的空间
3.开辟空间深拷贝赋值数据
4.返回自身对象
—- Tip:异常安全问题 在赋值期间发生异常 保证赋值两者的数据安全

*类成员有指针的时候 考虑拷贝构造和析构还有运算符重载的安全性

vld.h: 检测内存泄露的库

Question: C++的类的初始的函数有六个 分别是什么?
explicit关键字的用法?
如何把一个只有一个数据成员的对象直接给一个该数据的变量赋值?(Test t(200); int value = t;)

成员函数中用const修饰的方法:
void Test::fun()const;
实际上相当于
void Test::fun(const Test * const this);
本质上就是不能修改this所指的对象的值;
***tips: 常方法不能调用有可能改变对象的值的成员函数;

成员函数中的static修饰的方法:
static修饰的变量以及函数,被所有对象共享,没有this指针;
***tips: 静态方法不能调用成员函数,因为它是被所有类对象共享的;

用friend关键字修饰的友元函数可以访问私有成员;
— 常用来重载流运算符;

运算符重载:

   **不能使用的重载运算符:**
       三目运算符: ?:
       成员访问符: . .*
       字长访问符: sizeof
       作用域符:   ::
++运算符的重载:
    前置++: Test operator++();
    后置++: Test operator++(int);
        此处的int仅作为标记使用;
流运算符重载:
   friend ostream& operator<<(ostream &out, const Test &t);
   {
       out << t.data;
       return out;
   }

作为友元函数进行重载;

C++如何实现的重载:
   编译器在汇编阶段根据函数的参数通过自己的一套命名方式
   将函数进行一系列重命名,翻译成另一个具有唯一性的名字(带上函数的参数)

   当加入extern "C" 修饰函数的时候用C的模式汇编

空间分配(new && delete):

new 等同于 C 语言中的 (强制转化 *)malloc(sizeof(类型));

   int *p   = new int(10);     //新建一个值为10的整形
   int *p   = new int[10];     //新建一个有10个成员的整形数组

   int *p   = new Test;        //调用构造函数申请空间(如果要求有参数必须写参数)

   int *p   = new Test[10];    //构造10个对象!
                               //Tips: 如果要直接构造,一定要有默认(带参)的构造函数
   delete []p;                 //*** 通过delete删除掉连续申请的对象空间 否则内存泄露
       //方括号只起到标记作用,标识是释放一个数组空间

new的步骤:
1.申请空间;
2.调用构造函数在申请的空间内构造对象;

delete的步骤:
1.调用析构函数析构对象;
2.释放空间;

模板:

   #include <typeinfo>
   template<typename Type>
   Max(Type a, Type b)
   {
       cout<<typeid(Type).name()<<endl;
       //打印出Type的类型
       return a>b ? a:b;
   }

实现是先通过一系列操作与函数模板, 制作出相应类型的模板函数
最后再用模板函数来实现函数功能

类的形式类似;

可以直接调用:
Max(1,2);
Max(‘A’, ‘X’);
或者显式调用:
Max(1,2);
Max(‘A’, ‘X’);

Gdb调试:

1.g++ -o -g
2.gdb
3.list
4.b 加断点
5.run

new && delete:

1.new operator -> 1)分配空间 2)构造函数
              (直接使用 new 关键字)
2.operator new -> 只分配空间
              (直接使用 operator new 关键字)

可以重载new操作符来影响其分配空间的操作

   void *operator new(size_t sz)
   {
       void *p = malloc(sz);
       return p;
   }

要求返回值void * 传入参数 size_t

同时如果你重载了new操作符,就要求你重载delete操作符

   void operator delete(void *p)
   {
       free(p);
   }

*Tips:free 与 malloc对应
new 与 delete对应
operator new 与 operator delete 对应

同理 new[] 与 delete[] 也可以重载
实际上new[] 在申请空间的时候,
头部会多出一部分cookie空间, 大小为一个指针的大小
存储着用户的信息:起始位置,释放多少个对象
此时才可以以delete[]来释放相应的空间

类里面也可以重载new delete操作符,而且会被对象优先使用

如果是void*p = new Test(10);
那么delete p的时候 不会调用类的析构函数;

3.placement new

通过malloc开辟空间之后
int p = (int )malloc(sizeof(int) * 10)
可以通过new(p)int(10)来对申请的空间进行赋值
这种语法称之为定位new

这样的new也是可以重载的:

   void *operator new(size_t sz, void *data, int pos)
   {
       return (data + pos);
   }

则使用方法变为

new(p, 3)int(200);

对p所指的第三个位置进行赋值200的操作

继承和多态:

子类虽然公有继承了基类的私有成员
但是依然不能在自己的方法中改变基类
正确的用法是在基类中设置相应的设置方法来设置基类的成员

父类的信息能否被子类调动?
   ***父类任意私有数据都不能被子类直接调用
   但是父类的公有方法与保护方法都可以被子类的方法调用
   只有公有方法可以被对象直接访问
保护方法存在的意义:
   ***保护只在继承的时候体现它的性质
   不想被外部的对象调用, 为了给子类提供借口而存在
   其他一切特点等同于私有

class C: D
默认是私有继承 (class C: private D)

多继承:
   多继承的构造函数顺序就是继承列表从左往右
   同时先构造成员的类对象再构造自身类对象
   构造函数书写方法:
   C(a, b, c): A(a), B(b), C(c){}
   子类要调用基类的构造方法

   二义性:
       父类有同名的变量
       那么需要通过加入 父类:: 来避免二义性
虚继承:
   可以避免继承同一个基类产生变量的二义性
同名隐藏:
   如果子类和父类有同名的方法
   那么父类的同名方法会完全被隐藏(哪怕是重载)
   但是可以通过使用::这个来直接调用父类方法

看书:
1.重载 2.覆盖 3.隐藏

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值