function semantics

  . Static member function can not be: a direct access nonstatic transactions; 2 it can not be be const.

A, Member of various ways to call

1.1Nonstatic member function (non-static member function) is called by

  The compiler will convert the function of the member instance like "function instance nonmember. Conversion steps

  1. rewriting function signature (mean: prototype) placed in an additional parameter to member function, the conduit for providing an access to the class object to call this function. The additional parameter is referred to this pointer

float Point3d::magnitude3d() const{...}

// expansion process non-const nonstatic member of 
Point3d Point3d :: Magnitude (Point3d * const  the this )

If a member function is const, then becomes:
// expansion process const nonstatic member of: 
 Point3d Point3d :: magnitued ( const Point3d * const  the this )  

  2. Each "nonstatic data member access operation of" this pointer to accessed via

  3. The member function to re-write an external function. After the function name "mangling" process, making it a unique vocabulary in the program

Name of special treatment (name mangling)

  1. In general, the former name of the member will be coupled with the name of the class, the formation of a unique name
  2. Plus the parameter list
  3. Plus parameter types

1.2Virtual Member Functions (virtual member function)

  If normalize () is a virtual member function, then the following call:

ptr-> the normalize ();
 // will be converted to the interior: 
(* ptr-> the vptr [ . 1 ]) (PTR);
  1. vptr a pointer that produced by a compiler, point virtual table. It was placed in each class object "statement has (or inherited from) one or more virtual functions" in
  2. 1 is the index of the virtual table slot, associated to normalize () function
  3. This represents a second pointer ptr

  If you use the class object to call a virtual function, its analytical methods and non-static member function. Respect to the upper section of the normalize () function.

1.3Static member Function (static member function)

  static member function outside the class will be presented in the statement, and to give a proper name through the mangled, an object, a reference or pointer to call static member function will be converted into ordinary nonmember function call.

  1. It can not directly access nonstatic members class of
  2. It can not be declared cosnt, volatile or virtual
  3. It does not need through the class object and are called - though most of the time it is being called

  Taking the address of a static member function, access will be its location in memory, which is its address. Since this pointer is not static member function, so the address type is not a "class member function pointer points to", but a "nonmember function pointer"

Two, Virtual Member Functions (virtual member function)

  During execution, you need to do during a call to get some relevant information, if the information on the ptr, then a pointer or a reference to holding two pieces of information

  1. He referenced object address
  2. Some type of object code, or a structure (containing certain information to the correct resolution function address)

  This information will put additional burden and reduce the space connection compatibility with C language program pointer, so this additional information should be placed on the object itself.

  To support virtual function mechanism, must first be able to have some form of polymorphic objects "actuator type determination method" in C ++, polymorphism represents "In a public base class pointer (or reference) addressing a derived class object "means.

  1. Polymorphic function ptr play a major delivery mechanism, through it, we can use a set of public derived type anywhere in the program, this polymorphism is known to be negative
  2. When pointed out that the object is actually used multi-state will become positive

  To see whether to support a multi-state class to see if he has no virtual function, and therefore we need this additional execution of information

ptr->z();
  1. ptr within the meaning of true type of the object, which allows us to select the correct z () entity.
  2. z () physical location, so we can call it.

  In the implementation, may be added in two members of each class object polymorphic body

  1. A string or a number representing the type of class.
  2. A pointer to a table in the implementation of virtual functions of the address table with the program.

  virutual functions address table at compile time you can get the address of the virtual function, in addition, this group address is fixed, the implementation period is not possible to add or replace it, as the program executes, the size and form of content do not change, it can access and which is constructed entirely by the compiler, the actuator does not require any access.

  1. To find the table, each class object pointer is placed on an internally generated by the compiler, pointing to the table
  2. In order to find the function address, each virutual function is assigned a value table index

  Implementation period need to do is activate the virutal function in a particular record virutual function address

  Virtual a class only has a table, all the physical addresses of active virtual functions for each function table corresponding class object connotation, these active virtual function comprising:

  1. This class of functions defined entity, it will overwrite (overriging) base class virtual function a function entity may exist
  2. Inherited from the base class function entity, which is to determine the circumstances will occur when virtual function should not be written in the derived class
  3. Entity pure_virtual_called () function

  Each faction has a virtual function have a fixed value of the index, the index value in the entire inheritance hierarchy associated with a particular virtual function.

  The picture above shows a single case of succession

  1. It can be inherited virutal functions of the base class function entity declared, correct to say that the function is the address of the entity will be copied to the derived class virtual table corresponding slot in
  2. It can use your own function entity, which means that its own function physical address must be placed in the corresponding slot.
  3. It can also add a new virtual function. This time virtual table will increase the size of a slot, and the new function will be put into a physical address in the slot.

  If such a call

ptr->z();

  So how I had just enough time to set virtual function calls at compile it?

  1. In general, we do not know the actual type ptr referents, but we can know, to be accessed via a virtual table ptr of the object;
  2. Although we do not know which z () is called, but I know the address of each z () function are placed slot4 in, so that we can be transformed into:
(* Ptr-> vptr [ 4 ]) (ptr);

2.1 virtual function under multiple inheritance

class Base1 {
public:
    Base1();
    virtual ~Base1();
    virtual void speakClearly();
    virtual Base1 *clone() const;
protected:
    float data_Base1;
}
class Base2 {
public:
    Base2();
    virtual ~Base1();
    virtual void mumble();
    virtual Base2 *clone() const;
protected:
    float data_Base2;
}
class Derived : public Base1, public Base2 {
public:
    Derived();
    virtual ~Derived();
    virtual Derived *clone() const;
protected:
    float data_Derived;
}

  在多重继承中支持virtual function,复杂度在于第二个及后继的base classes上以及必须在执行期调整this指针。如上derived支持virtual function难度落在base2上。

Base2 *pbase2=new Derived;
//新对象的地址必须调整用以指向Base2 subobject,编译期会产生以下代码:
Derived *temp=new Derived;
Base2 *pbase2=temp?temp+sizeof(Base1):0;

//如果没有这样调整指针指向“非多态运用”会失败

//当删除pbase2时,先调用正确的virtual destructor函数,然后实行delete运算符,pbase2需要调整以指出完整的对象起点
 delete pbase2;

  this指针的调整操作必须在执行期完成,即offset的大小及把offset加到this指针上头必须让编译器在某个地方插入。

Base1 *pbase1=new Derived;
Base2 *pbase2=new Derived;

//以下操作执行相同的Derived destructor
delete pbase1;
delete pbase2;
  1. pbase1不需要调整this指针,因为Base1是最左短的base class,它指向Derived对象的起始处,virtual table slot放的是真正的destructor地址
  2. pbase2需要调整this指针,其virtual table slot需要相关的thunk地址

  Thunk技术:以适当的offset值调整this指针;跳转到虚函数。
  比如代码delete pbase2;thunk看起来如下:

this += sizeof(base1);
Derived::~Derived(this);

  而对于多重继承的派生类,一个derived class内含n-1个额外的虚表,其中n表示上一层继承的base class的个数,因此对于该继承体系中的Derived,会产生2个虚表,分别对应于Base1和Base2。

  针对每一个虚表,Derived对象中由对应的vptr,vptrs将在构造函数中设定初值。这一点可以说明构造函数一般不能是虚函数。
  Derived关联的两个虚表可能有这样的名称:

  1. vptr_Derived; //主要表格,关联到Base1
  2. vtbl_Base2_Derived; //次要表格,关联到Base2

  当将一个derived对象地址给指定的Base1指针或derived指针,被处理virtual table是主要表格,当derived对象地址给base2指针,被处理的virtual table是次要表格,sun编译器将多个virtual table连锁为一个,指向次要表格的指针,可由主要表格的名称加一个offset获得。每个class只有个具名的virtual table。

2.2虚继承的情况

class Point2d {
public:
    Point2d(float x = 0.0, float y = 0.0);
    virtual ~Point2d();
    virtual void mumble();
    virtual float z();
protected:
    float _x, _y;
};
class Point3d : public virtual Point2d {
public:
    Point3d(float x = 0.0, float y = 0.0, float z = 0.0);
    ~Point3d();
    float z();
protected:
    float _z;
}

  当point3有唯一一个base class时,继承对象模型也不像非虚拟单一继承那么简单。

 

  不要在virtual base class中声明nonstatic data member

三、函数效能

  对于nonmember、static member、nonstatic member函数都是转换为一样的形式,所以三者的效率完全一样。inline函数不仅能节省一般函数调用所带来的额外负担,也提供了程序优化的额外机会。

四、指向Member Functions的指针

double (Point::*pmf)();//声明pmf函数指针指向Point的member function

//指定其值
pmf = &Point::y;//y是Point的成员函数
//或者直接声明是赋值
double (Point::*pmf)() = &Point::y;
  
//假设一个Point对象origin以及一个Point指针ptr,那么可以这样调用:
(origin.*pmf)();
//或者
(ptr->*pmf)();
//编译器的转化为
(pmf)(&origin);
//或者
(pmf)(ptr);

  指向member function的指针声明语法以及指向“member selection运算符”的指针,其作用是作为this指针的空间保留

  使用一个“member function指针”如果并不用于virtual function、多重继承、virtual base class 等情况,并不会比使用一个“nonmember function指针”的成本更高。

 4.1指向Virtual Member Functions的指针

float (Point::*pmf)()=&Point::z;
Point *ptr=new Point;

//直接调用
ptr->z();
//pmf间接调用
(ptr->*pmf)();

  内部转换为:(*ptr->vptr[(int)pmf])(ptr);

  对于一个virtual member function,取地址,得到的是一个索引值。

  假设有如下Point声明

class Point {
public:
    virtual ~Point();
    float x();
    float y();
    virtua float z();
}

  取析构函数的地址:&Point::~Point();得到索引1;取&Point::x()得到函数在内存中的地址;取&Point::z()得到索引2

  但是“指向member function的指针”评估求值,会议内该值有两种意义而复杂化,对于nonvirtual该值是一个地址,对于virtual该值是索引值,但是如何辨别这个数值是内存地址还是索引值呢?

(((int)pmf) & ~127) ? (*pmf)(ptr) : (*ptr->vptr[(int)pmf]());

  对于x&~127=0 当x<=127,这种实现技巧必须假设继承体系中的virtual functions的个数小于128.

Guess you like

Origin www.cnblogs.com/tianzeng/p/12153391.html