向下类型转换有时是必须的,在可控的环境中可以有效使用向下类型强制转换。此时应该利用dynamic_cast,它使用该类型对象的内置知识来防止无意义的类型转换。如果对指针不能进行动态类型转换,指针值为NULL而不是指向无意义的数据。如果未能对对象的引用使用dynamic_cast,则会抛出std::bad_cast异常。
总结:只有在必要并且保证使用动态类型转换的时候使用向下类型强制转换。
继承以实现多态
纯虚方法与抽象基类:
纯虚方法是指在类定义中显式未定义的方法。包含纯虚方法的类称为抽象类,抽象类不能实例化,但是仍然可以使用抽象类类型的指针和引用。
语法:virtual string getString() const = 0;
如果二个要实现二个兄弟类的互相转换,可以在兄弟类中增加一个类型构造函数,它看起来和复制构造函数很像,但是复制构造函数引用同一类型的对象,而类型构造函数引用的是兄弟类的对象。
如:
class SpreadsheetCell
{code};
class StringSpreadsheetCell:public SpreadsheetCell
{
public:
StringSpreadsheetCell();
StringSpreadsheetCell(const DoubleSpreadsheetCell& inDoubelCell);
};
class DoubleSpreadsheetCell:public SpreadsheetCell
{code};
使用类型构造函数,给定DoubleSpreadsheetCell很容易构造StringSpreadsheetCell。但是不要被类型转换所迷惑。从一个兄弟类转换到另一个兄弟类是不行的。除非重载类型转换操作符。
这样实现二个StringSpreadsheetCel、一个StringSpreadsheetCell
一个DoubleSpreadsheetCell、二个DoubelSpreadsheetCel相加就可以写一个公共的operator+重载了。
const StringSpreadsheetCell operator+( const StringSpreadsheetCell& lhs, const StringSpreadsheetCell& rhs)
{code}
多重继承:
从多个类中继承:
class A{code};
class B{code};
class C:public A,public B{};
C对象支持A和B中所有public方法和数据成员。
类C的方法可以访问A和B中的protected数据和方法。
C对象可以转换为A和B对象。
创建C对象时,会自动调用A和B的默认构造函数,调用顺序在类定义中这二个类的列出顺序。
撤销C对象时,会自动调用A和B的析构函数,调用顺序与类定义中这二个类的列出顺序相反。
命名冲突与二义基类:
名字二义性:
如果A和B都有一个public eat()方法,一旦C对象调用eat()方法,就会产生二义性(也可是是同名的数据成员)。
解决此二义性:
1.static_cast(myC.eat()); //向上转换产生切割调用A的eat()方法
2.myC.A::eat(); //使用作用域解析操作符调用A的eat()方法
引起二义性问题的另外一种原因就是:从同一个类继承二次。
class A{code};
class B:public A{code};
class C:public A,public B{};
二义基类:
多个父类自身有共同的父类。
使用这种继承体系,最好是使上层的共同父类成为抽象基类,所有方法都声明为纯虚方法。