摘要: Builder模式仍然属于创建型模式,主要体现了OO中“封装”和“多态”两个特性。还是引一个简单的例子来说明Builder模式的意义。假设我们设计的游戏中需要创建一个比较复杂的房屋对象,房屋对象有很多部分组成,比如说有门,窗户,墙,地板等等。当我们在将这个房屋实现之后,可能随着需求的改变需要对门进行更换,将原来的木门换成铁门。这时候的问题就是:如何改...
阅读全文
摘要: FactoryMethod模式属于23种设计模式中的创建型模式,解决的是如何“new”的问题。引例:还是先从简单的例子入手FactoryMethod模式吧,现在需要一个汽车测试的环境来对汽车进行测试,我们很容易会这样设计
1/**/////////////////////////////////////////////// 2//汽车类 3...
阅读全文
摘要: 设计模式的目的就是尽量减少“变化”对程序的影响,尤其是对客户程序的影响。AbstractFactory模式作为创建型模式的一种,解决的就是“new”在变化中可能引起的问题。先来看看new有何种不好,举个创建汽车的车门的例子:很自然的一种想法是:Door *door = new Door();但是如果遇到创建老爷车的车门,创建现代车的车门,这段代码就无...
阅读全文
摘要: Strategy模式是设计模式中非常常用的一种设计模式,甚至在你没有学习过设计模式之前就已经使用过这种模式。先看个简单的例子吧:比如说你要写个List的容器,需要有一个Sort方法。但是对于容器中不同类型的对象Sort方法可能会不一样,比如说Point类型可能根据point到原点的距离或者point的xy之和来比较大小。一种很自然的想法就是:
1void sort()2{3 ...
阅读全文
摘要: 引例:银行现在的业务大多有提醒业务,比如我们用信用卡消费的时候银行会有短信通知和Email通知等方法立即提醒客户账户发生了变化。这就是典型的Observer模式,A(账户)发生变化之后通知B(手机)和C(Email),以后也许还会通知D(电话)等等。。。程序设计中也会遇到很多这样的问题,比如说MFC中的Document/View架构,Document中的数据变化会立即通知View的显示也相应变化,...
阅读全文
上C++课程的时候老师总是鼓吹模板如何重要,但是真正上课时候却将该部分跳过。平时做项目写程序虽然天天接触STL,但说到如何实现模板真的是道不出其一二。现将这几天看C++Primer中的一些重要概念提取出来,以备不时之需。
1,模板的用处。
模板其实也是多态思想的一种体现,不过不是C++那个运行时多态,而是编译时多态。那么用在什么地方呢?个人感觉用的最多的是在数据结构中,一些经典的数据结构(Queue,Stack)用模板类实现确实事半功倍。至于其他地方嘛。。。也许是自己的功力不够,几乎就没有用过(设计模式不也是一样的道理嘛,囧)
2,模板定义
模板函数定义:
template<typename T>
int compare(const T &v1,const T &v2);
内联函数:
inline template<typename T> int compare(const T &v1,const T &v2);
模板类定义:
template<class Type> class Queue
{
public:
Queue();
Type T& front();
//......
}
3,模板类实例化
Queue<int> qi;
其实这个不就是和STL一模一样嘛?确实是的,STL不就是帮我们这些经典的数据结构一一实现了嘛?
4,友元的在模板类的使用
friend class Queue<Type>;
这样就将Queue这个模板类设为了友元,之前必须要有Queue<Type>的声明,如template<class Type> class Queue;
5,static在模板类中
一个模板类会有多个static实例成员,但每种类型的模板类只有一个static成员!
比如说Queue<int>有一个static成员,Queue<string>也有一个static成员
讨论:
如果你讨厌链接错误,那么你一定觉得模板这个东西是让人讨厌的,起码编译器是很讨厌模板的,要知道在实例化时才会确定模板中T的类型,再根据他生成相应的代码是件很麻烦的事情,模板类在这个问题上显得尤其麻烦。
一般写类都是将定义和声明放在两个文件中的,这样清晰明了,但是在模板类中绝对不可以!编译器会找不到你定义的那些方法!
所以说,写模板类的话就请写在一个文件中吧,MS到现在还把export留作未来使用的关键字在,我们暂时就不要指望这个了吧!
看模板类的时候发现有些地方使用到了友元,上课学的记不得了,赶紧温习下。。。
友元概念就不罗嗦了,使用也简单,就两种形式:
1.友元函数:friend ret-type classname::funname(....);
2.友元类:friend class classname;
唯一要注意的就是不管是友元函数还是友元类,定义友元关系前必须先声明
友元类其实还是有些故事要说的,一旦类继承起来友元关系还是有些小复杂的,下面简单说明:
C中声明A是其友元类,那么最基本的就是A可以使用C中的private方法或者对象。
图中可见,A是B的基类,C是D的基类。ABCD中就有如下关系:
1.B新增的方法不能访问C的私有成员
2.B从A继承而来的方法可以访问C的私有成员
3.A只能访问D中从C中继承而来的私有成员,D中新增的私有成员不能访问!
总结起来就是友元关系不可以继承,但对已有的方法来说访问权限不改变。如果改写基类的方法则访问权限改变
PS : 要特别谢谢有朋友留言纠正了我的错误,这次将测试用代码一并贴出
class C
{
friend class A;
private :
int numC;
};
class D : public C
{
private:
int numD;
};
class A
{
public:
//A是C的友元,可以访问C的私有成员
void getFromC()
{
C c;
c.numC = 100;
cout<<"getFromC in A : numC = "<<c.numC<<endl;
};
//A不是D的友元,不能访问D中新增的私有成员,但可以访问D从C中继承而来的私有成员
void getFromD()
{
D d;
d.numC = 23;
cout<<"getFromD in A : numC = "<<d.numC<<endl;
//d.numD = 24;
//cout<<"getFromD in A : numD = "<<d.numD<<endl;
}
};
class B :public A
{
public:
//友元关系不能继承,新增的方法不能访问C的私有成员
// int getNumB()
// {
// C c;
// c.numC = 100;
// return c.numC;
// }
//改写方法后对C访问权限改变,不能访问C的私有成员
// void getFromC()
// {
// C c;
// c.numC = 100;
// cout<<"getFromC in B : numC = "<<c.numC<<endl;
// }
};
int _tmain(int argc, _TCHAR* argv[])
{
A a;
a.getFromC();//输出——getFromC in A : numC = 100
a.getFromD();//输出——getFromD in A : numC = 23
B b;
b.getFromC();//输出——getFromC in A : numC = 100
//调用的还是A::getFromC
return 0;
}
项目里的阴影实现一直没有做,考虑到毕竟是室内的漫游项目,对阴影要求效果并不是很高,就准备用烘培试试看。况且烘培不用改代码,模型改好后一劳永逸。
有图有真相,看图说话
Max里随便加了两盏灯,模型用的是我最喜欢的1Box+4Cylinder,可以看出地板效果还是挺好的。光线有些暗,把material文件的emissive改大些就行,懒得弄了。
接下来就把项目的文件全部baking出来吧,好大的工作量-_-|