1、关于String的一些操作,遇到过几次,但我一次也没有去总结过。
写出string 的赋值函数:
class String
{
// 赋值函数
String & operate=(const String &other);
// 相加函数,如果没有friend 修饰则只许有一个右侧参数
friend String operate+( const String &s1, const String &s2);
private:
char *m_data;
}
String 的赋值函数operate = 的实现如下:
String & String::operate=(const String &other)
{
if (this == &other)
return *this;
delete m_data;
m_data = new char[strlen(other.data)+1];
strcpy(m_data, other.data);
return *this; // 返回的是 *this 的引用,无需拷贝过程
}
对于赋值函数,应当用“引用传递”的方式返回String 对象。如果用“值传递”的
方式,虽然功能仍然正确,但由于return 语句要把 *this 拷贝到保存返回值的外部存储
单元之中,增加了不必要的开销,降低了赋值函数的效率
String 的相加函数operate + 的实现如下:
String operate+(const String &s1, const String &s2)
{
String temp;
delete temp.data; // temp.data 是仅含‘/0’的字符串
temp.data = new char[strlen(s1.data) + strlen(s2.data) +1];
strcpy(temp.data, s1.data);
strcat(temp.data, s2.data);
return temp;
}
对于相加函数,应当用“值传递”的方式返回String 对象。如果改用“引用传递”,
那么函数返回值是一个指向局部对象temp 的“引用”。由于temp 在函数结束时被自动销
毁,将导致返回的“引用”无效。
当然还有写构造函数,析构函数的,下次再整理。
2、#include “filename.h”和 #include <filename.h>的区别
这个题居然很常出现,我就不知道有什么意义。
对于#include “filename.h” ,编译器从用户的工作路径开始搜索filename.h
对于#include <filename.h> ,编译器从标准库路径开始搜索filename.h
3、写一个最简单的strcpy函数,这个出现很高,借鉴CSDN上的一篇文章,标准写法应该如下:
char * strcpy( char *strDest, const char *strSrc )
{
assert( (strDest != NULL) && (strSrc != NULL) );
char *address = strDest;
while( (*strDest++ = * strSrc++) != ‘/0’ );
return address;
}
4、分别给出BOOL,int,float,指针变量 与“零值”比较的 if 语句。这个我至今只遇到过两家公司出这样的题。
BOOL型变量:if(!var)
int型变量: if(var==0)
float型变量:
const float EPSINON = 0.00001;
if ((x >= - EPSINON) && (x <= EPSINON)
指针变量: if(var==NULL)
5、关于sizeof(classname)的一些题。
1、class A
{
}
sizeof(A) = 1
2、class A
{
viod function();
}
sizeof(A) = 1
3、class A
{
virtual void function();
}
sizeof(A)= 4
4、class A
{
virtual void function();
private:
int a;
}
sizeof(A) = 8
关于sizeof
sizeof(type)最小会给1,即使class A什么都没有。这么设计也许是为了让对象的数组可以通过其大小得到数组元素的数量吧。(如果为0,则元素数量也许为无限大- -)
成员函数并不占用对象的空间。它是该类所有对象的公共部分。
但当类含有虚方法时,则该类的对象都需要有一个指针指向虚函数表。
5、若析构函数为虚函数,那么当使用delete释放基类指针指向的派生类对象时,先调用派生类的析构函数,再调用基类的析构函数。
6、虚基类 :
如果某个派生类的部分或全部直接基类是从另一个共同的基类派生而来,在这些基类中,从上一级基类继承来的成员就有相同的名称,则在这个派生类中访问这个共同的基类中的成员时,可能会产生二义性,此时,可定义虚基类。这就要求在其直接基类的定义中,使用关键字 virtual 将那个共同的基类定义为虚基类,其语法形式如下:
class 派生类名: virtual 派生方式 基类
虚基类的初始化与一般的多重继承的初始化在语法上是一样的 ,但构造函数的调用顺序不同,虚基类构造函数的调用顺序是这样规定的:
1) 在同一层次中,先调用虚基类的构造函数,接下来依次是非虚基类的构造函数,对象成员的构造函数,派生类的构造函数。
2) 若同一层次中包含多个虚基类,这些虚基类的构造函数按对他们说明的先后次序调用
3) 若虚基类由非虚基类派生而来,则仍然先调用基类构造函数,再调用派生类构造函数。