今天面试了艺动娱乐,小弟还没到这种大公司面试过,心里有有些小紧张。艺动的架势确实也与小弟之前面试的公司不一样,虽然感觉今天的面试多半会被Pass掉,但是,多少也算有了点大公司面试的经验。
之前一直在小公司做单机游戏,项目经验也不足,最主要还是自己学东西不求甚解,知识面太窄,导致今天的面试非常惨淡!!!
先总结下经验:自己虽然也用C++开发1年多了,但是,对C++的特性还是不够了解,C++底层的东西理解还是不够。今天,面试官问了我三个关于C++的问题,我竟然一个都不会。真是羞愧,吃一堑,长一智,先在这里记录下吧!
1.C++的菱形继承问题:
先写一个简单的例子:
#include <iostream>
using namespace std;
class A
{
public:
private:
};
class B : public A
{
public:
private:
};
class C : public A
{
public:
private:
};
class D : public B, public C
{
public:
private:
};
int main()
{
return 0 ;
}
这样A,B,C,D四个类就是一个菱形继承的关系,D中会保留两个A对象,这样会占用双倍的内存。同时,当A中有属性和函数的时候还可能会出现二义性问题。
将B,C类的代码改成如下就能解决菱形继承问题:
class B : virtual public A
{
public:
private:
};
class C : virtual public A
{
public:
private:
};
但是,并不能解决二义性问题。
解决二义性问题,需要从D类中入手,可以在D中实现同样的属性或者方法,指出调用的是B的还是C的,或者是什么时候调用B的什么时候调用C的。
或者,在调用的时候指明,调用的是C的方法,还是B的方法。
2.C++反射机制的实现
听到这个问题的时候,真的有点懵,因为,我之前只是听说过Java的反射机制(而且还忘了怎么实现),现在让我说C++如何实现反射机制,顿时不知道如何入手了。
回来在网上找了找,还真有,真是感谢网上的各位大神啊!
http://blog.csdn.net/nighsen/article/details/6407017
http://blog.csdn.net/cen616899547/article/details/9317323
这两位位大神的博客很详细。非常感谢!!!
下面是我仿照两位大神的方法的实现:
ReFactory:工厂类
.h
#ifndef _RE_FACTORY_H_
#define _RE_FACTORY_H_
#include <string>
#include <map>
#include <iostream>
using namespace std;
typedef void* (*CreateFuntion)(void);//<回调函数
//@biref 设计为单例类
class ReFactory
{
public:
static ReFactory * s_pReFactory ;
static ReFactory * getInstance() ;
public:
ReFactory (){}
~ReFactory (){}
void* getClassByName(string name) ;
void registClass(string name,CreateFuntion func) ;
private:
std::map<string,CreateFuntion> m_classMap ;
};
#endif
.cpp
#include "ReFactory.h"
ReFactory * ReFactory::s_pReFactory = NULL ;
ReFactory * ReFactory::getInstance()
{
if (s_pReFactory == NULL)
{
s_pReFactory = new ReFactory() ;
}
return s_pReFactory ;
}
void* ReFactory::getClassByName(string name)
{
std::map<std::string,CreateFuntion>::const_iterator itor ;
itor = m_classMap.find(name) ;
if (itor == m_classMap.end())
{
return NULL ;
}
else
{
return itor->second() ;
}
}
void ReFactory::registClass(string name,CreateFuntion func)
{
m_classMap.insert(std::make_pair(name,func)) ;
}
ReRegister
.h
#ifndef _RE_REGISTER_CLASS_H_
#define _RE_REGISTER_CLASS_H_
#include "ReFactory.h"
class ReRegisterClass
{
public:
ReRegisterClass (string name,CreateFuntion func){
ReFactory::getInstance()->registClass(name,func) ;
}
~ReRegisterClass (){}
private:
};
template<class T,const char name[]>
class ReRegister
{
public:
ReRegister()
{
const ReRegisterClass temp = rc ;
}
~ReRegister();
static void* createInstance()
{
return new T ;
}
public:
static const ReRegisterClass rc ;
};
template<class T,const char name[]>
const RegistyClass ReRegister<T,name>::rc(name,ReRegister<T,name>::createInstance()) ;
#define DEFINE_RE_CLASS(class_name)\
char nameArray[]=#class_name;\
class class_name:public ReRegister<class_name,nameArray>
#define DEFINE_RE_CLASS_EX(class_name,father_class) \
char nameArray[]=#class_name;\
class class_name:public ReRegister<class_name,nameArray>,public father_class
DEFINE_RE_CLASS(Coco)
{
public:
void Display()
{
printf("Coco");
}
};
#endif
main
#include "Factory.h"
#include "ReRegistClass.h"
#include "ReFactory.h"
int main()
{
Coco * co = (Coco*)ReFactory::getInstance()->getClassByName("Coco") ;
co->Display() ;
getchar() ;
return 0;
}
这样就OK了!!
虽然实现了反射,但是,这也不是真正意义上的反射,真正意义上的反射只有java,C#那种有虚拟机的语言才能实现。
3.C++lambad表达式
lambad表达式又叫匿名函数,在我看来就是能直接把函数体写在参数中了。
Lambda表达式是定义一个没有名称,也不需要显示类定义的函数对象。一般用来将函数作为实参传递到另一个函数。
相比于定义和创建一个常规的函数对象而言,lambda表达式非常容易使用和理解,而且需要的代码也较少。
[](double x){return x*x*x;}
[]lambda的引导,它标志着lambda表达式的开始,()是lambda表达式的参数列表。lambda表达式不允许有默认参数,而且,参数列表的长度是不可变的。{}是lambda表达式的主体,可以包含多条语句。返回值类型可以指定,默认为void.
引导中可以包含一个捕获子句,用来确定lambda主题如何访问封闭作用域中的变量。
如果,没有符号,代表表面封闭作用域没有可以让lambad中访问的变量,如果有,可写成[=],这种情况下,可以访问,但是不能改变原始值。写成[&]可以改变。
若要捕获一个特定的对象[&name]需要这样写,多个用逗号分开。
测试代码:
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
int main()
{
int x = 4;
int y = 5;
int z = 0 ;
z = []{return 10 + 10 ;}() ;//<普通
z = [=]{return x + y;}() ;//<捕获但不改变
z = [&]{x += 10 ; return x + y ;}() ;//<捕获,改变
z = [&x,y]{x += 10 ; return x + y;;}() ;//<捕获,改变特定值
z = [=]() mutable ->int { x += 10 ;return x + y; }();//<捕获,不改变原始值
printf("x:%d;z:%d",x,z) ;
getchar() ;
return 0 ;
}
4.C++是不是类型安全的编程语言?
答案是否定的。C++不是类型安全的编程语言,在C++中0和1是可以当作bool类型来使用的,但是,在类型安全的编程语言中是不能这样使用的,比如在Java中。