继承类通过using声明使用私有继承类的方法;
class Student
{
public:
using std::string::size;
};
cout<<stu.size();
相当于string::size();
多重继承
虚基类相当于单独继承了该基类,在派生类的构造函数中必须显式调用其构造函数,不能使用间接类来传递参数,所以相当于又继承了一次,
除此之外还要重新修改基类的方法;
混合使用虚基类和非虚基类当导致拥有多个基类对象;
模板:同级之间的代码重用使用模板;
template<class T1,class T2>
class SortedArray{
};
显式具体化
template<>class SortedArray<const char*,const int>
{
...
};
部分具体化
template <class T1> class SortedArray<T1,int>
{
};
template后边声明的是没有被具体化的类型参数,如果指定所有的类型,将导致显式具体化,
如果有多个模板供使用,编译器将选择具体化程度最高的模板;
显式具体化>部分具体化>无具体化;
对于指针类型也可以部分具体化;
template <calss T*> class Feb{};
部分具体化可以具有各种限制
template <class T1,class T2,class T3>class Feb{};
template <class T1,class T2> class Feb<T1,T1,T2>{};
嵌套模板:
template <class T>
class time{
public:
template<class S>
void blab(T t,S s);
}
template<class T>
template<class S>
void time<T> ::blab(T t,S s){};
模板可以作为结构,类,模板类的成员,以实现STL设计;
一种模板类包含另一种模板类,将实现更为泛型的编程;
模板可以包含类型参数和非类型参数,模板还可以包含本身就是模板的参数,
template<template <class T>class Thing>
class GrabP{};
即特定的类作为一个参数;同时类还是一个模板;
模板类和友元;
模板的友元分为三类:
非模板友元,约束模板友元,非约束模板友元
模板的友元如果要使用模板作为参数,需要为友元指定显式具体化,即重载,
模板类的友元函数,问题在于如果传递模板类的参数,该传递哪种?基于此分为三类:
1.非模板友元:(1)不需要类参数;是所有实例化模板类的友元,没有意义,因为友元本身就是为了使用模板的私有成员,除非模板类中的私有成员是静态成员,那可以使用::静态成员名来访问,除此之外都需要传递对象参数;
(2)需要类参数:此时需要用到重载的技术,为每一个友元重载一个函数;
template <class T>
class HasFriend{
friend void report(HasFriend<T>&);
};
为此需要生成 具体化;
void report(HasFriend<int>&){};
此时report不是友元,所以需要许多的report重载
归纳:总之非模板友元函数如果要使用类中的数据,必须进行具体化,如果是使用静态数据那倒不用;
2.约束模板友元函数:
提供模板类型,在使用时需要通过显式实例化来访问,其实也是根据参数类型生成一个友元函数的实例,而这个函数恰好在某个类的友元列表内;相比于一般的友元,这个友元是在调用时才生成的,当实例化一个模板类时,也就获得了他的友元列表,即是一种宏替换;类中的友元是一种具体化,但不是完全的具体化,
3.非约束模板友元函数:
约束模板友元函数是在类外声明的具体化,非约束模板友元函数是在类内声明的,约束模板友元函数让每个模板类都只有一个友元,而非约束让每一个实例化的函数都是所有实例化类的友元;可用性更强;
模板别名:
模板别名让人们能够像使用一般类型一样使用模板类;
typedef array<double,12> arrd;
arrd gallons;//array<double,12>gaalons;
template<typename T>
using arrtype=array<T,12>;
arrtype<double>gallons//array<double,12>gallons;
using与typedef;
非类型参数: