C++面向对象高级编程(下)
一起怀着希望,拥抱暖意,不负春光,不负梦想。愿春回大地时,万物更新、硝烟皆逝。没有一个冬天不可逾越,没有一个春天不会到来。灾难总是突如其来,但这种时候我们更该众志成城、团结一心。我们相信,一切终将过去,定会春暖花开。
今天,junkle想继续说一下C++面向对象的下一个部分。今天主要有:
①转换函数(explicit关键字)(补充上部分)
②模板嵌套模板
③模板参数偏特化
④传递模板参数
⑤const关键字使用
⑥虚函数原理(特别重要的一部分)
转换函数指的是:某个类型的数据是否可以根据类的构造函数转换成类的问题(需要借助explicit关键字)。
比如以下例子:
如果代码想这些让编译器通过,有这几种可能:
TranderFun rr = t1 + 30.0;
Ⅰ、编译器尝试将 30.0 转换成 t1 类型的对象,然后编译器如果能找到类重载的 + 号运算符,那么会将生成的类赋值给左边。
Ⅱ、编译器如果没有找到重载的 + 号运算符,那么编译器会尝试着将t1 转换成 double 类型(重载operator double()),然后将两个 double 进行相加,相加完成以后会尝试将 double 转换为 t1 类型的类进行赋值。
综合可以看出,只要这段代码想通过编译,必须不能加explicit关键字。
template<class T1 = int, class T2 = double>class X{public:T1 firstl;T2 first2;X():firstl(T1()), first2(T2()){}template<class U1>X(vector<U1> &v1){cout << "fefe" << endl;}};
vector<int> v1;X<int, double> x1(v1);
函数模板偏特化有好几种类型,下面介绍一种方式:
Ⅰ、如果模板传的参数是普通对象,那么调用第一套代码。
Ⅱ、如果模板传的参数是指针对象,那么调用第二套代码。
//偏特化template<class T>class w1{public:w1(T *p){cout << "Z" << endl;cout << *p << endl;}};template<class T>class w1<T *>{public:w1(T *p){cout << "P" << endl;}};
template<class T,template<class T>class _Container_ >class First{public:_Container_<T> c1;};
template<class T = int,class T1 = list<T> >class Second{public:};
//注意区分这两个 一个可以传递模板 一个只能传递特化的模板 不一样First<int, wei1> f1;Second<int, list<int>> s1;
const关键字有两种用法:
Ⅰ、定义成员变量(不能修改值)
Ⅱ、定义成员函数(函数内只能修改const的变量)
注意:const是重载的一部分。
C++语法规定,在类内有相同成员函数,区别只是有无const。那么,const对象只能调用const成员变量(如果只有非const成员变量,那么const对象不能调用),非const对象只能调用非const成员函数。
示例代码如下:
namespace wei {class weixiaotao{public:int a;void show(int a){cout << "fei" << endl;}void show() const{cout << "const" << endl;}};}
虚函数原理
虚函数原理可谓是C++最最重要的特性之一。
下面先上大师图:
我的理解:一个类对象调用成员函数,分为静态绑定和动态绑定;
动态绑定就是所谓的虚函数实现多态。
满足动态绑定的三个条件:
·指针调用
·是否是虚函数
·是否是向上转型(也就是是否是父类指针指向子类成员)
静态绑定是正常函数调用。
namespace HELLO{class MyclassA{public:MyclassA(){}virtual void show1(){cout << "A :HELLO1" << endl;}virtual void show2(){cout << "A :HELLO2" << endl;}};//继承虚函数1 重写虚函数2class MyclassB : public MyclassA{public:MyclassB(){}virtual void show2(){cout << "B :HELLO2" << endl;}void print()const{cout << "const的使用" << endl;}/*void print(){cout << "粉色粉色发const的使用" << endl;}*/};}int main(){HELLO::MyclassB b;HELLO::MyclassB b3;b3.print();typedef void(*p)();p pFun = (p)(*(int *)*(int *)(&b));p pFun1 = (p)(*(((int *)*(int *)(&b)) + 1));pFun1();cout << sizeof(FILE) << endl;system("pause");return 0;}
为什么静态函数中不能操作成员变量呢?
答:因为不会传递this指针
注意:虚函数表中的顺序和父类虚函数的顺序一致,也就是如果子类重写了虚函数,那么该虚函数在表中的顺序和在父类中的顺序是一致的只不过是改变了函数指针的指向。
