1.在面向对象中可能出现下面的情况
基类指针指向子类对象
基类引用成为子类对象的别名
Base* b = new Derived();
Base& r = *b;
2.动态类型是相对于静态类型而言
静态类型:变量(对象)自身的类型
动态类型:指针(引用)所指的对象实际类型
基类指针是否可以强制转换为子类指针取决于动态类型
比如在继承体系中:Derived继承于Base。
期望的类型是Base,实际指向的却是Derived类型,这时在做类型转换时就有可能有问题。
Base* b = new Derived();
Base& r = *b;
Derived* d = static_cast<Derived*>(b) //这样转换可能有问题
代码:
class Base
{
public:
virtual string type()
{
return "Base";
}
};
class Derived : public Base
{
public:
string type()
{
return "Derived";
}
void printf()
{
cout << "I'm Derived" << endl;
}
};
class Child : public Base
{
public:
string type()
{
return "Child";
}
};
void test(Base* b)
{
//Derived* d = static_cast<Derived*>(b);
cout << b->type() << endl;
if(b->type() == "Derived")
{
Derived* d = static_cast<Derived*>(b);
d->printf();
}
cout << dynamic_cast<Derived*>(b) << endl; //继承体系下有虚函数可以调用dynamic_cast,仅仅告诉我们转换是否成功,并不知道具体类型。
}
int main(int argc,char* argv[])
{
Base b;
Derived d;
Child c;
test(&b);
test(&d);
test(&c);
return 0;
}
3.多态解决方案的缺陷
1.必须从基类开始提供类型虚函数
2.所有派生类都必须重写类型虚函数
3.每个派生类的类型名必须唯一
4.C++提供了typeid关键字用于获取类型信息
typeid关键字返回对应参数的类型信息
typeid返回一个type_info类对象
当typeid的参数为NULL时将抛出异常
5.typeid的注意事项
1.当参数为类型时,返回静态类型信息
2.当参数为变量时:
不存在虚函数表时返回静态类型信息
存在虚函数表时返回动态类型信息
3.typeid:在不同的编译器下处理类型名有可能是不同的
typeid的使用:
class Base
{
public:
virtual ~Base()
{
}
};
class Derived : public Base
{
public:
void printf()
{
cout << "I'm Derived" << endl;
}
};
void test(Base* b)
{
const type_info& tb = typeid(*b);
cout << tb.name() << endl;
}
int main(int argc,char* argv[])
{
int i = 0;
const type_info& tiv = typeid(i);
const type_info& tii = typeid(int);
cout << (tiv == tii) << endl; 输出1,说明类型名相同
Base b;
Derived d;
test(&b);
test(&d);
return 0;
}
当基类Base没有虚函数时,返回4Base,4Base
当基类Base有虚函数时,返回4Base和7Derived,不同编译器返回的类型名有可能不一样