C++ function机制

C++在布局以及时间上的主要额外负担是有virtual引发的。
1. 虚函数机制(virtual function):用于支持执行期绑定
2. 虚继承(virtual base class): 用于出如今继承体系中的多个baseclass,有一个单一而被共享的实体。


C++支持3中成员函数: 
static member function
nonstatic member function
virtual memeber function


Nonstatic member function(非静态成员函数)
C++的设计准则:非静态成员函数和非成员函数具备相同的效率。其实编译器在编译时,将成员函数实体转换成对等的非成员函数实体,这也是为何在调用成员函数时,会传递this指针了。

好比非成员函数以下:
float compute3d(const Point3d *_this)
{
        return sqrt( _this->x * _this->x +
                     _this->y * _this->y +
                     _this->z * _this->z);
}



使用的时候传入对象指针,经过对象指针获取成员。若是是成员函数,多是这样的。
float compute3d()
{
    return sqrt(x * x + y * y + z *z);
}



可是在真正调用的时候,实际上是通过转化的。
1. 改写函数的signature(函数原型) ,用来安插一个额外的参数到成员函数中,提供存取对象属性的渠道,即this指针。
float compute3d(Point3d * const this)

2. 将对每个对非静态的属性的存取操做改成由this指针来操做,即将
return sqrt(x * x + y * y + z *z)改成
 return sqrt( this->x * this->x +
                   this->y * this->y +
                   this->z * this->z);

3. 将成员函数从新写为外部函数,对函数名称进行"nabgkubg"处理,时期成为独一无二的词汇。
extern compute3d_8Point3dFv(register Point3d *const this);

那对象会对象指针在调用时即发生以下变化:
obj.compute3d();------------------compute3d_8Point3dFv(&obj);
p->compute3d();------------------compute3d_8Point3dFv(p);
(obj为对象,p为对象指针)



virtual member function(虚拟成员函数)

C++中的虚函数的做用主要是实现了多态的机制。多态就是用父指针指向子类 对象,而后经过父类的指针调用实际子类的成员函数。ios

// virtualFunTest.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>

using namespace std;

class Base
{		
	public:
				virtual void f()
				{
					cout<<"Base: f()"<<endl;
				};

				virtual void g()
				{
					cout<<"Base: g()"<<endl;
				};
				
				virtual void h()
				{
					cout<<"Base: h()"<<endl;
				};
};


class Derive1 : public Base
{
	public:	
				virtual void f()
					{
						cout<<"Derive1: f()"<<endl;
					};

					virtual void g1()
					{
						cout<<"Derive1: g1()"<<endl;
					};

					virtual void h1()
					{
						cout<<"Derive1: h1()"<<endl;
					};
};

void Test1()
{
			Base b;
			typedef void(*Fun)(void);
			Fun pFun = NULL;

			//int*(&b) 虚函数表指针
			cout<<"对象其实地址: "<<&b<<endl;
			cout << "虚函数表地址:" << (int*)(&b) << endl;

			//*(int*)(&b) 指虚函数表  (int*)*(int*)(&b)表示虚函数表的第一个内容
			//能够理解(int*)*(int*)(&b)+0  (int*)*(int*)(&b)为数组首地址
			
			// Invoke the first virtual function
			pFun = (Fun)*((int*)*(int*)(&b)+0); // Base::f()	
			cout << "虚函数表 — 第一个函数地址:" << (int*)*(int*)(&b) << endl;
			
			pFun();

			pFun= (Fun)*((int*)*(int*)(&b)+1); // Base::g()	
			cout << "虚函数表 — 第二个函数地址:" << (int*)*(int*)(&b) + 1<< endl;

			pFun();

			pFun=(Fun)*((int*)*(int*)(&b)+2); // Base::h()
			cout << "虚函数表 — 第三个函数地址:" << (int*)*(int*)(&b) + 2<< endl;

			pFun();
}

void Test2()
{
			Base *p = new Derive1();
		    typedef void(*Fun)(void);
			Fun pFun = NULL;

			//int*(&b) 虚函数表指针
			cout<<"对象其实地址: "<<p<<endl;
			cout << "虚函数表地址:" << (int*)p<< endl;
			
			
			pFun = (Fun)*((int*)*(int*)p+0); 
			cout << "虚函数表 — 第一个函数地址:" <<(int*)*(int*)p<< endl;			
			pFun();

			pFun=  (Fun)*((int*)*(int*)p+1); 
			cout << "虚函数表 — 第二个函数地址:" <<(int*)*(int*)p+1<< endl;
			pFun();

			pFun=(Fun)*((int*)*(int*)p+2); 
			cout << "虚函数表 — 第三个函数地址:" << (int*)*(int*)p+2<< endl;
			pFun();

			pFun= (Fun)*((int*)*(int*)p+3); 
			cout << "虚函数表 — 第四个函数地址:" << (int*)*(int*)p+3<< endl;
			pFun();

			pFun= (Fun)*((int*)*(int*)p+4); 
			cout << "虚函数表 — 第五个函数地址:" << (int*)*(int*)p+4<< endl;
			pFun();
}



Test1结果/Test2结果数组


虚函数表中按照顺序依次存放了类中定义的虚函数。app



因而可知,在虚函数表中,函数地址的顺序为:函数

Derive1:f() , Base:g(), Base:h(), Derive1:g1(), Derive1:h1(), 地址由低到高,个人理解是,子类在创建本身的虚函数表时,布局

首先将父类的虚函数表内容拷贝过来,而后检查其中的函数有没有被覆盖,若是有覆盖,替换掉,而后把其余新添加的虚函数按照顺序依次添加到虚函数表中。this

此处没有探讨多重继承的状况。spa



C++静态成员函数和静态成员设计

静态成员变量:每个对象都共享一个变量,static成员是独立于类的任意对象而存在的;每一个static成员是与类关联的,和该类的对象无关。3d

 静态成员函数:静态成员函数能够直接访问静态成员变量,若是要访问非静态成员变量的话,只能访问某一个对象的非静态成员变量和静态成员函数。能够传一个对象的指针,引用等参数给这个静态成员函数。指针

class Account
{
   	public:
	void applyint()
	{
		amount += amount * interestRate;		
	}

	static double rate()
	{
		return interestRate;
	}

	static void rate(double); //sets a new rate

	private:
	std::string owner;
	double amount;
	static double interestRate;
	static double initRate();
}

该类时一个银行帐户类,不一样的帐户对应不一样的客户,可是利率是同样的。独立于具体客户对象的,全部interestRate为静态成员。

静态成员的访问。经过对象,对象指针以及类名加做用域操做符在访问。

Account ac1;
Account *ac2 = &ac1;

double rate;
rate = ac1.rate();
rate = ac2->rate();
rate = Account::rate();

普通的成员函数访问静态成员时,无需做用域操做符,能够直接访问,好比applyinit方法。

static data member存放于程序的data segment(数据段)中

static成员函数

在类外部定义类的静态成员函数时,无需static关键字,在声明处有static便可。

static成员是类的组成部分,但不是对象的组成部分,全部是不会像static成员函数传递this指针的。

static成员函数不能声明为const。由于成员函数被const修饰后表示不会修改对象得属性,可是静态成员函数不属于对象。

相关文章
相关标签/搜索