1)虚继承与虚基类的学习
using namespace std;
class Parent
{
public:
int m_;
};
//何为虚继承和虚基类:用virtual继承父类,(所有相关的类都必须virtual父类才可以),则叫虚继承;
//被虚继承的父类则就叫虚基类,(父类没有任何改变,只是叫法不同而已);
//虚继承对子类没有任何影响,主要是影响的孙子类,为了孙子也是拼了。所谓前人栽树,后人乘凉,是也!
class A : virtual public Parent //A和B都得虚继承才可以
{
};
class B : virtual public Parent
{
};
class C :public A, public B
{
};
int main()
{
C c;
c.m_ = 20; //如果不是虚继承,这条语句会出现访问不明确
cout << c.m_ << endl;
return 0;
}
2)类的成员函数指针使用方法
class A
{
public:
A() :m_(23) {
cout << "A constructor--" << endl; }
void func(int aa)
{
cout << "m_ is: "<<m_ + aa << endl;
}
private:
int m_;
};
int main()
{
A a1;
void(A::*fptr)(int); //定义类的成员函数指针
fptr = &A::func; //给类的成员函数指针赋值,有真正的地址
//如果使用类的成员函数指针,则必须有类对象,用类对象调用;
(a1.*fptr)(10);//利用类的成员函数指针调用类的成员函数
return 0;
}
// fun(2.3f); 或 fun(2.3F); 调用形参为 float 的函数
// fun(2.3); 调用形参为 double 的函数,因为C/C++浮点型数据默认是 double 型
3)模板函数,包括模板参数和非模板参数的使用方法
函数模板的使用:
using namespace std;
// 模板和泛型编程
// 所谓泛型编程,是独立于任何特定类型的编程方式;
// 模板是泛型编程的基础;
// 模板是将类型定义为参数的程序方式;
// 在模板参数列表里,除了可以定义【类型参数】外,还可以定义【非类型参数】;重点!
// 非类型参数不可以用typename/class来修饰,必须用具体的类型来修饰
// 非类型参数必须是常量表达式,因为在编译阶段就得确认具体数值;
// 函数模板通常放在".h"中;
// 在头文件定义函数模板,在多个.cpp文件包含,不会造成重定义,如果是普通文件就会造成重定义;
//类型模板参数
template<typename T> //里面的参数叫模板参数列表
T add(T a, T b)
{
return a + b;
}
//非类型模板参数
template<int a,int b>
int add1()
{
return a + b;
}
//既有类型模板参数,又有非类型模板参数
template<int a, int b, typename T> //定义顺序和调用顺序必须一致,否则编译错误
int add2(T mm)
{
return (int)mm + a + b;
}
int main()
{
int ret = add<int>(4, 5); //类型模板参数调用方法
ret = add1<3, 2>();//非类型模板参数调用方法! 用尖括号里面的数值给非类型参数传递数值
ret = add2<10,20,int>(3);//既有类型模板参数,又有非类型模板参数的调用方法
cout << ret << endl;
return 0;
}
4)类模板定义及使用
4.1)(类模板的类型参数使用)
template<class T>
class MyVector
{
public:
MyVector(T a);
typedef T* iterator; //迭代器
MyVector& operator=(const MyVector&);//赋值运算符重载;在类模板内部使用模板名可以不写模板参数;
//MyVector<T>& operator&(const MyVector<T>&);
iterator begin();
iterator end();
void func(void);
T a_;
};
//类模板的构造函数
template<class T>
MyVector<T>::MyVector(T a):a_(a)
{
cout << "MyVector constructor a_: " << a_ << endl;
}
//类模板的类外定义成员函数,把【模板参数名】列出来
template<class T>
void MyVector<T>::func(void) //void MyVector::func(void)这样写是错误的,MyVector是类模板名,不是类名
{
}
//模板类名字的使用,如下所示,必须在类模板中添加"<T>",使之成为【类名】;
template<class T>
MyVector<T>& MyVector<T>::operator=(const MyVector<T>&) //类模板的赋值运算符重载
{
return *this;
}
主函数调用如下:
MyVector<int> vec(23); //如果调用的话,编译器会生成一个具体的类;
MyVector<double> vec1(23);//又生成另外一个类对象
4.2)(类模板的非类型参数使用)
//类模板的非类型参数使用方法
template<class T,int N = 4> //默认模板参数只在声明中体现
class Test
{
public:
void printMsg(T tmp);
};
template<class T, int N> //如果int改为浮点型,则编译出错
void Test<T,N>::printMsg(T tmp)
{
cout << N + tmp << endl;
}
int main()
{
Test<int> t1; //使用默认值4
Test<int,5> t2; //从新设置非类型模板参数
t1.printMsg(5);
t2.printMsg(5);
return 0;
}
5)typename使用场合,默认模板参数及趣闻写法分析
(1) 定义模板参数,如:template<typename T>
(2) 修饰类型,如下代码:
using namespace std;
template<class T>
class MyVector
{
public:
MyVector(T a);
typedef T* iterator; //迭代器
MyVector& operator=(const MyVector&);//赋值运算符重载;在类模板内部使用模板名可以不写模板参数;
iterator begin();
iterator end();
void func(void);
T a_;
};
//类模板的构造函数
template<class T>
MyVector<T>::MyVector(T a):a_(a)
{
cout << "MyVector constructor a_: " << a_ << endl;
}
//类模板的类外定义成员函数,把【模板参数名】列出来
template<class T>
void MyVector<T>::func(void) //void MyVector::func(void)这样写是错误的,MyVector是类模板名,不是类名
{
}
//模板类名字的使用,如下所示,必须在类模板中添加"<T>",使之成为【类名】;
template<class T>
MyVector<T>& MyVector<T>::operator=(const MyVector<T>&) //类模板的赋值运算符重载
{
return *this;
}
//使用类的类型成员,iterator是一个类型
//typename这里的目的:就是告诉编译器"iterator"是一个类型,不是类的静态成员变量;
template<class T>
typename MyVector<T>::iterator MyVector<T>::begin() //iterator MyVector<T>::begin()这样写是不对的,
{
}
template<class T>
typename MyVector<T>::iterator MyVector<T>::end()
{
}
6)函数指针做其他函数的参数
typedef int(*fptr)(int, int);
int func(int a, int b)
{
return a + b;
}
void test(int a, int b, fptr fn)
{
cout << fn(a, b) << endl;
}
int main()
{
test(2, 4, func);
return 0;
}
7)仿函数(可调用对象的类) //注意:此案例即可调用函数模板,又可调用类模板
int func(int a, int b)
{
return a + b;
}
template<typename T, typename F>
void test(T a, T b, F fn)
{
cout << fn(a, b) << endl;
}
class A
{
public:
A()
{
cout << "constructor" << endl;
}
int operator()(int a, int b)const
{
return a + b;
}
};
int main()
{
test(2, 4, func);
A a;
test(2, 7, a);
return 0;
}
8)默认类型模板参数及默认非类型参数
template<class T = int> //默认类型模板参数
class A
{
public:
A(T val):val_(val){
}
void printMsg(void) {
cout << "val_is: " << val_ << endl; }
private:
T val_;
};
int main()
{
A<> a1(10); //使用的是默认类型模板参数
a1.printMsg();
A<double> a2(2.9);
a2.printMsg(); //使用的是double类型模板参数
return 0;
}
默认非类型模板参数
template<int N = 5> //模板类的非类型默认参数
class A
{
public:
int arr[N];
private:
};
int main()
{
A<> a1;//使用的是非类型默认参数
A<10>a2; //定义10个数组元素
return 0;
}