首页 > 代码库 > C++学习笔记13-类继承
C++学习笔记13-类继承
1. 类模板的 static 成员[不同于C#中的static]
类模板可以像任意其他类一样声明static 成员。以下代码:
template <classT> class Foo { public: static std::size_tcount() { return ctr; } // other interfacemembers private: static std::size_tctr; // otherimplementation members };
定义了名为Foo 的类模板,它有一个名为count 的public static 成员函数和一个名为ctr 的private static 数据成员。
Foo 类的每个实例化有自己的static 成员:
// Each object sharesthe same Foo<int>::ctrand Foo<int>::count members Foo<int> fi,fi2, fi3; // has static membersFoo<string>::ctrand Foo<string>::count Foo<string> fs;
每个实例化表示截然不同的类型,所以给定实例外星人所有对象都共享一个static 成员。因此,Foo<int>类型的任意对象共享同一static 成员ctr,Foo<string> 类型的对象共享另一个不同的 ctr 成员。
使用类模板的static 成员通常,可以通过类类型的对象访问类模板的static 成员,或者通过使用作用域操作符直接访问成员。当然,当试图通过类使用static 成员的时候,必须引用实际的实例化:
Foo<int> fi, fi2; // instantiates Foo<int> class size_t ct =Foo<int>::count(); // instantiates Foo<int>::count ct = fi.count(); // ok: usesFoo<int>::count ct = fi2.count(); // ok: usesFoo<int>::count ct = Foo::count(); // error: whichtemplate instantiation?
与任意其他成员函数一样,static成员函数只有在程序中使用时才进行实例化。
2. 句柄类
类管理继承层次中对象的指针,句柄的用户不必管理指
向这些对象的指针,用户代码可以使用句柄类来编写。句柄能够动态分配和释放
相关继承类的对象,并且将所有“实际”工作转发给继承层次中的底层类。
3. 转换与多个基类
class X { ... }; class A { ... }; class B : public A {... }; class C : private B {... }; class D : public X,public C { ... }; // 如果有,下面转换中哪些是不允许的? D *pd = new D; (a) X *px = pd; (c) B *pb = pd; // X, B is private (b) A *pa = pd; // X, B is private (d) C *pc = pd;
4. 虚继承
虚继承是一种机制,类通过虚继承指出它希望共享其虚基类的状态。在虚继承下,对给定虚基类,无论该类在派生层次中作为虚基类出现多少次,只继承一个共享的基类子对象。共享的基类子对象称为虚基类。
5. 怎样构造虚继承的对象
让我们看看虚继承情况下怎样构造对象。
Bear::Bear(std::string name, bool onExhibit): ZooAnimal(name,onExhibit, "Bear") { } Raccoon::Raccoon(std::string name, boolonExhibit) : ZooAnimal(name,onExhibit, "Raccoon") { } // 虽然ZooAnimal 不是Panda 的直接基类,但是Panda 构造函数也初始化 ZooAnimal 基类: Panda::Panda(std::string name, bool onExhibit) : ZooAnimal(name,onExhibit, "Panda"), Bear(name,onExhibit),Raccoon(name, onExhibit), Endangered(Endangered::critical), sleeping_flag(false){ } Bear winnie("pooh"); // Bear constructor initializes ZooAnimal Raccoon meeko("meeko"); // Raccoon constructor initializesZooAnimal Panda yolo("yolo"); // Panda constructor initializes ZooAnimal
当创建Panda 对象的时候,
1. 首先使用构造函数初始化列表中指定的初始化式构造ZooAnimal 部分。
2. 接下来,构造Bear 部分。忽略Bear 的用于ZooAnimal 构造函数初始化列表的初始化式。
3. 然后,构造Raccoon 部分,再次忽略ZooAnimal 初始化式。
4. 最后,构造Panda 部分。
如果Panda 构造函数不显式初始化ZooAnimal 基类,就使用ZooAnimal 默认构造函数;如果ZooAnimal 没有默认构造函数,则代码出错。当编译Panda 构造函数的定义时,编译器将给出一个错误信息。
6. 小结
在抛出异常的时候,会终止当前正在执行的函数并开始查找最近的catch 子句,在查找catch子句的时候,作为异常处理的一部分,将撤销退出函数内部定义的局部变量。这种撤销对象提供了一个重要的编程技术,称为“资源分配即初始化”(RAII)。命名空间是一种机制,用于管理用独立供应商开发的代码建立的大型复杂应用程序。一个命名空间就是一个作用域,其中可以定义对象、类型、函数、模板和其他命名空间。标准库就定义在名为std 的命名空间中。
通过using 声明,当前作用域中就都可以访问某个命名空间中的名字了。
当然,也可以通过using 指示将一个命名空间中的所有名字带入当前作用域,但这种做法很不安全。
从概念上来看,多重继承很简单:派生类可以继承多个直接基类,派生类对象由派生部分和每个基类所贡献的基类部分构成。虽然多重继承概念简单,但细节可能非常复杂,尤其是,继承多个基类引入了新的名字冲突可能性,并且会导致对对象基类中的名字的引用出现二义性。
一个类继承多个直接基类的时候,那些类有可能本身还共享另一个基类。在这种情况下,中间类可以选择使用虚继承,声明愿意与层次中虚继承同一基类的其他类共享虚基类。用这种方法,后代派生类中将只有一个共享虚基类的副本。