C++ 工程师面试体验(4)

5、引用与多态的关系?
 
引用是除指针外另一个可以产生多态效果的手段。这意味着,一个基类的引用可以指向它的派生类实例。

Class A;
Class B:Class A{...}; 
B b;
A& ref = b;

6、引用与指针的区别?
指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。
程序中使用指针,程序的可读性差;
而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。
此外,就是上面提到的对函数传ref和pointer的区别。
 
7.实现strcpy
char *strcpy(char *strDest, const char *strSrc)
{
 if ( strDest == NULL || strSrc == NULL)
  return NULL ;
 if ( strDest == strSrc)
  return strDest ;
 char *tempptr = strDest ;
 while( (*strDest++ = *strSrC++) != ‘\0’)
 ;
 return tempptr ;
}

8.实现String类
 
一直都有这么一个印象:拷贝构造函数和赋值函数是一对好基友。
 
class String
{
public:
String(const char *str = NULL); // 通用构造函数
String(const String &another); // 拷贝构造函数
~ String(); // 析构函数
String & operater =(const String &rhs); // 赋值函数
private:
char *m_data; // 用于保存字符串
};

String::String(const char *str)
{
  if ( str == NULL ) //strlen在参数为NULL时会抛异常才会有这步判断
    {
      m_data = new char[1] ;
      m_data[0] = '\0' ;
    }
  else
    {
      m_data = new char[strlen(str) + 1];
      strcpy(m_data,str);
    }
}

String::String(const String &another)          //拷贝构造函数
{
    m_data = new char[strlen(another.m_data) + 1];
    strcpy(m_data,other.m_data);
}

String& String::operator =(const String &rhs)  //赋值函数 
{
    if ( this == &rhs)
        return *this ;
    delete []m_data; //删除原来的数据,新开一块内存
    m_data = new char[strlen(rhs.m_data) + 1];
    strcpy(m_data,rhs.m_data);
    return *this ;
}

String::~String()
{
    delete []m_data ;
}

9.#include<file.h> 与 #include "file.h"的区别?
 
答:前者是从Standard Library的路径寻找和引用file.h,而后者是从当前工作路径搜寻并引用file.h。
 
 
10.C++用C编译器编译后的函数为什么要加入extend "C"?
 
两者编译机制不一样,为了能够和谐工作,extend "c"告诉C++编译器,这里按照C编译器的处理方式编译链接就行了。
一句话:实现C++与C及其它语言的混合编程
(我在JNI的时候用到这玩意~)
 
为什么?
 
作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。
函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为:
void foo( int x, int y );  
该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。
 
现在假设模块A是C语言编译后的,模块B是C++模块。B中调用A的函数。
 
这样,模块B中调用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错;
它会在连接阶段中从模块A编译生成的目标代码中找到此函数。
 
 
 
11.面向对象的三个基本特征,并简单叙述之?
 
1. 封装:
 
将客观事物抽象成类,每个类对自身的数据和方法实行protection(private, protected,public)


2. 继承:
 
广义的继承有三种实现形式:实现继承(指使用基类的属性和方法而无需额外编码的能力)、可视继承(子窗体使用父窗体的外观和实现代码)、接口继承(仅使用属性和方法,实现滞后到子类实现)。前两种(类继承)和后一种(对象组合=>接口继承以及纯虚函数)构成了功能复用的两种方式。


3. 多态:
 
是将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。
简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。
 
 
12. 重载(overload)和重写(overried)的区别?
 
从定义上来说:
 
重载:是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。
重写:是指子类重新定义父类虚函数的方法。


从实现原理上来说:
 
重载:编译器根据函数不同的参数表,对同名函数的名称做修饰,然后这些同名函数就成了不同的函数(至少对于编译器来说是这样的)。如,有两个同名函数:function func(p:integer):integer;和function func(p:string):integer;。那么编译器做过修饰后的函数名称可能是这样的:int_func、str_func。对于这两个函数的调用,在编译器间就已经确定了,是静态的。也就是说,它们的地址在编译期就绑定了(早绑定),因此,重载和多态无关!


重写:和多态真正相关。当子类重新定义了父类的虚函数后,父类指针根据赋给它的不同的子类指针,动态的调用属于子类的该函数,这样的函数调用在编译期间是无法确定的(调用的子类的虚函数的地址无法给出)。因此,这样的函数地址是在运行期绑定的(晚绑定)。

13. 如何判断一段程序是由C 编译程序还是由C++编译程序编译的?

#ifdef __cplusplus
cout<<"C++";
#else
cout<<"c";
#endif

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/1a08bec43ddd6a6c35cd0aeab7392303.html