vlambda博客
学习文章列表

C++面向对象高级编程(下)

一起怀着希望,拥抱暖意,不负春光,不负梦想。愿春回大地时,万物更新、硝烟皆逝。没有一个冬天不可逾越,没有一个春天不会到来。灾难总是突如其来,但这种时候我们更该众志成城、团结一心。我们相信,一切终将过去,定会春暖花开。


C++面向对象高级编程(下)

今天,junkle想继续说一下C++面向对象的下一个部分。今天主要有:

①转换函数(explicit关键字)(补充上部分)

②模板嵌套模板

模板参数偏特化

④传递模板参数

const关键字使用

⑥虚函数原理(特别重要的一部分)

C++面向对象高级编程(下)

1

转换函数(explicit关键字)(补充上部分)


C++面向对象高级编程(下)

转换函数指的是:某个类型的数据是否可以根据类的构造函数转换成类的问题(需要借助explicit关键字)

比如以下例子:

如果代码想这些让编译器通过,有这几种可能:

TranderFun rr = t1 + 30.0;


Ⅰ、编译器尝试将 30.0 转换成 t1 类型的对象,然后编译器如果能找到类重载的 + 号运算符,那么会将生成的类赋值给左边。


Ⅱ、编译器如果没有找到重载的 + 号运算符,那么编译器会尝试着将t1 转换成 double 类型(重载operator double()),然后将两个 double 进行相加,相加完成以后会尝试将 double 转换为 t1 类型的类进行赋值。


综合可以看出,只要这段代码想通过编译,必须不能加explicit关键字。


C++面向对象高级编程(下)

2

模板嵌套模板
C++面向对象高级编程(下)
下面这段代码可以看出,一共有三个模板参数,类头有两个,类内有一个。
C++面向对象高级编程(下)


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; }};
C++面向对象高级编程(下)
定义时候可以这样:
C++面向对象高级编程(下)

vector<int> v1;X<int, double> x1(v1);

3

模板参数偏特化
C++面向对象高级编程(下)

函数模板偏特化有好几种类型,下面介绍一种方式:

Ⅰ、如果模板传的参数是普通对象,那么调用第一套代码。

Ⅱ、如果模板传的参数是指针对象,那么调用第二套代码。

C++面向对象高级编程(下)


//偏特化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; }};



4

传递模板参数
这个可以进行传递模板,注意区分下面两种情况:
C++面向对象高级编程(下)
第一种:
C++面向对象高级编程(下)


template<class T,  template<class T> class _Container_ >class First{public: _Container_<T> c1;};


C++面向对象高级编程(下)
第二种:
C++面向对象高级编程(下)


template<class T = int,class T1 = list<T> >class Second{public:

};
C++面向对象高级编程(下)
下面区分两种定义对象的方式:
C++面向对象高级编程(下)


//注意区分这两个 一个可以传递模板 一个只能传递特化的模板 不一样 First<int, wei1> f1; Second<int, list<int>> s1;

5

const关键字使用
C++面向对象高级编程(下)

const关键字有两种用法:

Ⅰ、定义成员变量(不能修改值)

Ⅱ、定义成员函数(函数内只能修改const的变量)

注意:const是重载的一部分。

C++语法规定,在类内有相同成员函数,区别只是有无const。那么,const对象只能调用const成员变量(如果只有非const成员变量,那么const对象不能调用),非const对象只能调用非const成员函数。

示例代码如下:

C++面向对象高级编程(下)


namespace wei { class weixiaotao { public: int a; void show(int a){ cout << "fei" << endl; } void show() const{ cout << "const" << endl; } };}


C++面向对象高级编程(下)
侯捷大师经验:在写一个类的时候,成员函数是否加const是考量一个程序员功底的关键因素。所以,以后设计类的时候,在该加const的成员函数必须要加。
C++面向对象高级编程(下)

6

虚函数原理

C++面向对象高级编程(下)

虚函数原理可谓是C++最最重要的特性之一。

下面先上大师图:

我的理解:一个类对象调用成员函数,分为静态绑定和动态绑定;

动态绑定就是所谓的虚函数实现多态。

满足动态绑定的三个条件:       

 ·指针调用

 ·是否是虚函数

 ·是否是向上转型(也就是是否是父类指针指向子类成员)

静态绑定是正常函数调用。

C++面向对象高级编程(下)


C++面向对象高级编程(下)

C++面向对象高级编程(下)
当这个类中有虚函数的时候,编译器会维护一个vptr指针和vtbl表,上图可以看出,vptr指针总是在对象的最前面。一个vptr指针指向虚函数表,虚函数表记录的是虚函数和各个类重写函数的地址。通过,this指针找到子类或者父类的vptr指针,然后通过vptr指针找到虚函数表中对应的虚函数,实现多态。那么,我们可以试图通过vptr指针调用到虚函数。下面代码可以实现调用vptr指针。
C++面向对象高级编程(下)


namespace HELLO{ class MyclassA { public: MyclassA() {

}

virtual void show1(){ cout << "A :HELLO1" << endl; } virtual void show2(){ cout << "A :HELLO2" << endl;

} }; //继承虚函数1 重写虚函数2 class 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;}


C++面向对象高级编程(下)

为什么静态函数中不能操作成员变量呢?

答:因为不会传递this指针

C++面向对象高级编程(下)
C++面向对象高级编程(下)

注意:虚函数表中的顺序和父类虚函数的顺序一致,也就是如果子类重写了虚函数,那么该虚函数在表中的顺序和在父类中的顺序是一致的只不过是改变了函数指针的指向。