第七章 站在对象模型的尖端
第七章 站在对象模型的尖端
template
的实例化行为
template<class Type>
class Point {
public:
enum status { unallocated, normalized; }
Point(Type x = 0.0, Type y = 0.0, TYpe z = 0.0);
~Point();
void* operator() new (size_t);
void operator() delete(void*, size_t);
private:
static Point<Type> *freeList;
static int chunksize;
Type _x, _y, _z;
};
对于enum
类型和static
成员,Point<float>
和 Point<double>
会实例化两次,而且必须使用Point<flaot>::status
不能使用Point::statuc
来调用。
对于Point<float>* ptr = 0
编译器不需要实例化,因为其指向的对象是一个Point<float>
但其本身是一个指针,编译器没必要知道其内部的布局。但是对于Point<float> &ref = 0
编译器会通过如下方式将其实例化:
Point<float> tempory(float (0));
const Point<float> &ref = tempory;
模板类的成员函数只有在调用他的时候才会实例化,对于没有调用到的成员函数不会实例化。
template
的名称决议法
scope of the template definition
定义出template
的位置
scope of the template instantiation
实例化template
的位置
// scope of the template definition
extern double foo(double);
template <class type>
class ScopeRules {
public:
void invariant() { _memeber = foo(_val); }
type type_dependent() { return foo(_member); }
private:
int _Val;
type _member;
};
// scope of the template instantiation
extern int foo(int);
ScopeRules<int> src0;
src0.invariant()
调用的foo
是double(foo)
,因为foo
的类型和实例化无关,对于scope
来说只有double(foo)
这一种类型。
src0.type_depentent()
这里面foo
调用的是int foo(int)
函数的类型和实例化的类型有关,对于scope
来说一共有double foo(double)
和 int foo(int)
两种,这个时候因为_member
的类型为int
最终调用的是int foo(int)
类型。
但是如果src0
为unsigned int
或者 long
类型,会出现暧昧不清的情况。如果ScopeRules
按照 类类型进行实例化,如果没有定义向int
和 double
的类型转换运算符,会报错。
保证安全的向下类型转换
dynamic_cast
可以在执行期决定其运行成本,如果向下类型转换是安全的回传回一个类型的指针,如果是不安全的回返回空指针。
class node {....};
class type : public node {....};
class fct : public type {...};
class gen : public type { ... };
typedef type *ptype;
typedef fct *pfct;
simplify_conv_op(ptype pt) {
pfct pf = pfct(pt); //这种类型转换是不安全的,
}
我们通过使用dynamic_cast
来确保其类型的安全性。
simplify_conv_op(ptype pt) {
if (pfct pf = dynamic_cast<pfct>(pt)) {
// .....
} else {// .....}
}
dynamic_cast
如何确保其是安全的呢,以及为何dynamic_cast
相对于static_cast
的成本更高呢?
pfct
的一个类型描述器被编译器产生出来,由pt
指向的类对象描述其必须在执行期通过vptr
获得。会发生如下的转换:
((type_info*)(pt->vptr[0]))->_type_descriptor
type_info
类是C++定义的一个类型描述器类:
class type_info {
public:
virtual ~type_info();
bool operator==(const type_info& ) const;
bool operator!=(const type_info& ) const;
bool before(const type_info &) const;
const char* name() const;
private:
type_info(const type_info&);
type_info& operator=(const type_info& );
}
虚函数表的第一个slot
中包含type_info
的地址,两个类型描述器被交给runtime library
函数,比较之后告诉我们是否吻合。
dynamic_cast
也同样使用与引用,但是对于一个非类型安全的转换结果和指针不同。因为如果将一个引用设置为0,会产生一个临时性对象,临时性对象的初值被设置为0,引用被设置为临时性对象的别名。
当dynamic_cast
作用于引用时会发生如下情况:
- 如果引用真正参考到适当的派生类(包括下一层,下下一层等等),
downcast
会被执行。 - 如果引用不是一种真正的派生类,由于不能传回0,会抛出
bad_cast
异常。
simplify_conv_op(const Type &rt) {
try {
fct &rf = dynamic_cast<fct&>(rt);
....
} catch (bad_cast) {
...
}
}