关于继承的理解
C++中的类其实和C中的结构体差不多,都是自定义的数据结构,可以包含多个成员。这些成员在内存空间内按顺序连续存放,并且其访问作用域限定于结构体或类内部。
与C不同的是,类里面还可以包含方法。类方法的访问也限定在类内部的作用域,或者在C++中叫命名空间,类本身可以看作一个命令空间。
但C++是支持继承的,一个派生类继承了基类,就是将基类的成员也包含进来。同时此类的作用域内增加了基类的方法。
我们使用了继承的语法,翻译给编译器来说就是将基类里的内容也包含进来。类似于预处理的工作。这种机制节省了代码量,减少了工作量。但实际的结果来说还是一样的。举例来说:
class A {
public:
int a;
};
class B: public A {
public:
int b;
};
上面定义的类B,其实就是:
class B {
public:
int a;
int b;
};
只不过我们将B的定义分成了两部分,一部分在A类里,一部分在B类里,并且A和B两个类有继承的关系,可以使用多态功能。
关于模板的理解
模板这种机制也是为了帮助程序员减少工作量,降低复杂度,提高效率而产生的技术。
比如:
#include <stdio.h>
#include <string>
using namespace std;
template <class T>
class A{
public:
A(){}
A(int b, T _t):val(b),t(_t){}
T t;
int val;
};
int main()
{
A<string> a(1, "hello");
return 0;
}
而实际上,在使用模板类的时候,编译器在后台帮你根据模板类型,自动生成了相应的类的定义,只是这种处理是开发人员不可见的。
按照上面的例子,使用: A<string> a(1, "hello"); 时,就会生成一个包含string类型的类。如下所示:
class A{
public:
A(){}
A(int b, string _t):val(b),t(_t){}
string t;
int val;
};
如果你换一个模板参数,就会多定义一个相应类型的类。只是这些代码是中间产物,你看不见,但实际存在。
使用模板参数来作为基类
既然继承和模板都可以看作一种在代码形式上的组合,那能不能组合使用呢?是可以的。
可以使用模板来表示继承,会有更大的灵活性。
把一个类的基类定义为模板参数,这样在使用时,想继承哪个类就继承哪个类。根据需要决定使用哪个基类。
比如下面:
#include <stdio.h>
class A{
public:
void helloA(){printf("helloA.\n");}
};
template <class T>
class B : public T
{
};
int main()
{
B<A> b;
b.helloA();
return 0;
}
$ g++ -o test main.cpp
$ ./test
helloA
所以,我们利用了模板,将基类作为模板参数,使类的定义更加灵活。
这样避免了类的继承链的唯一性,可以像搭积木一样进行配置。
还可以将类的成员也作为模板参数,将其添加到模板参数中即可。
这种将模板参数作为基类的方法,有些场景下使用更加方便。
比如有A,B两个类,具有像相似的接口,但不同的功能。
你自己想定义的类,可能会用到A的功能,或者B的功能。
正常的话,你可能要定义两个类,一个继承A,一个继承B。
但这样就要定义两个类,可能这两个类除了基类不同,其他方面是一样的。
这时如果用模板来表示的话,就不会用重复代码,而且用起来很方便。