c++面试题

1、已知类String 的原型为:
class String
{
public:
String(const char *str = NULL); // 普通构造函数
String(const String &other); // 拷贝构造函数
~ String(void); // 析构函数
String & operate =(const String &other); // 赋值函数
private:
char *m_data; // 用于保存字符串
};
请编写String 的上述4 个函数。
答案:
String::String(const char *str)
{
if ( str == NULL ) //strlen在参数为NULL时会抛异常才会有这步判断
{
m_data = new char[1] ;
m_data[0] = '' ;
}
else
{
m_data = new char[strlen(str) + 1];
strcpy(m_data,str);
}
}
String::String(const String &other)
{
m_data = new char[strlen(other.m_data) + 1];
strcpy(m_data,other.m_data);
}
String & String::operator =(const String &other)
{
if ( this == &other)
return *this ;
delete []m_data;
m_data = new char[strlen(other.m_data) + 1];
strcpy(m_data,other.m_data);
return *this ;
}
String::~ String(void)
{
delete []m_data ;
}

2、虚函数?重虚函数?

    虚函数:为了动态绑定

    重虚函数:为了实现接口调用

动态绑定:对象的静态类型:
    对象在声明时采用的类型。
对象的动态类型:
    目前所指对象的类型。是在运行期决定的。对象的动态类型可以更改,但静态类型无法更改。
静态绑定:
    绑定的对象是静态类型,某特性依赖对象的静态类型,发生在编译期。
动态绑定:
    绑定的对象是动态类型,某特性依赖对象的动态类型,发生在运行期。
 

class A
{
    virtual void vfun();
};
class B : public A
{
    virtual void vfun();
};
class C : public A
{
    virtual void vfun();
};
B* pB = new B();    //pB的静态类型是B*,动态类型也是B*
A* pA = pB;            //pA的静态类型是A*,动态类型是B*
pA->vfun()和pB->vfun(); //调用的是同一个函数,因为虚函数的地址相同;
//因为有了virtual虚函数特性,pB的动态类型指向B*,因此先在B中查找,找到后直接调用;

3、new带括号和不带括号的区别?
    不带括号:如果这个类没有自定义的构造函数,也没有虚函数,则new时,不调用构造函数
    因此使用new时别不带括号

4、基类的析构函数为什么要使用虚函数?

      防止内存泄漏。想去借助父类指针去销毁子类对象的时候,不能去销毁子类对象。假如没有虚析构函数,释放一个由基类指针指向的派生类对象时,不会触发动态绑定,则只会调用基类的析构函数,不会调用派生类的。派生类中申请的空间则得不到释放导致内存泄漏。

    new一个对象时,构造函数先构造父类,再进子类;(像基建)

    释放对象时(借助父类指针去销毁子类对象的),如果这个基类析构函数没有加virtual,则直接进入到了父类的析构函数;

    如果基类析构函数有virtual修饰,则先析构子类,再析构父类。

class A
{
public:
	A()
	{
		int a = 3;
	}
	virtual ~A()
	{
		int a = 3;
	}
};
class B : public A
{
public:
	B()
	{
		int b = 3;
	}
	~B()
	{
		int b = 3;
	}
};

//因为有了virtual虚函数特性,pB的动态类型指向B*,因此先在B中查找,找到后直接调用;
int main()
{
	A* paa = new B();
	delete paa;
	return 1;
}

5、

    int k = 2;
    int* ptr1, *ptr2;
    ptr1 = &k;
    ptr2 = &k;

    k = *ptr1 + *ptr2;
    ptr2 = k;       //不能将int类型的值分配到int*类型的实体
    ptr1 = ptr2;
    k = *ptr1*(*ptr2);

6、关系运算符的结果值

关系运算符的值为真时,结果值都为1。关系运算符的值为假时,结果值都为0。

7、

class A
{
  virtual void func1();
  void func2();
}
Class B: class A
{
  void func1(){cout << "fun1 in class B" << endl;}
  virtual void func2(){cout << "fun2 in class B" << endl;}

A, A中的func1和B中的func2都是虚函数.
B, A中的func1和B中的func2都不是虚函数.
C, A中的func2是虚函数.,B中的func1不是虚函数.
D, A中的func2不是虚函数,B中的func1是虚函数.

答: A

8、野指针

    a、指针变量没有被初始化。指针变量被创建时不会自动生成NULL指针,它的值是随机的,所以要么设为NULL,要么指向合法的内存。

    b、指针被释放后,没有置NULL

9、内存布局

class CTest
{
    public:
        CTest():m_chData(‘\0’),m_nData(0)
        {
        }
        virtual void mem_fun(){}
    private:
        char m_chData;
        int m_nData;
        static char s_chData;
};
char CTest::s_chData=’\0’;

a、先找有没有virtual,有则需要建立虚表函数,sizeof(CTest) += 4;

b、啥都没有或者只有成员函数 sizeof(CTest) += 1;

c、static声明的成员变量属于类域,不算入对象中 sizeof(CTest) += 0;

d、以及需要注意对齐法则

10、堆、栈、全局变量、局部静态变量构造顺序

设已经有A,B,C,D4个类的定义,程序中A,B,C,D析构函数调用顺序为?    A B D C
C c;
void main()
{
    A*pa=new A();
    B b;
    static D d;
    delete pa;
}

对于类A,  是建立在堆上的对象指针pa, 手动释放

对于类B, 是建立在栈上的对象b,main函数结束就释放

构造的规则是预先构造全局变量。

规则是在同一个文件中的全局变量,先定义的变量先构造。

11、写出下面程序的输出结果

class A
{
public:
 void FuncA()
 {
     printf( "FuncA called\n" );
 }
 virtual void FuncB()
 {
     printf( "FuncB called\n" );
 }
};
class B : public A
{
public:
 void FuncA()
 {
     A::FuncA();
     printf( "FuncAB called\n" );
 }
 virtual void FuncB()
 {
     printf( "FuncBB called\n" );
 }
};
void main( void )
{
 B  b;
 A  *pa;
 pa = &b;
 A *pa2 = new A;
 pa->FuncA(); ( 3)
 pa->FuncB(); ( 4)
 pa2->FuncA(); ( 5)
 pa2->FuncB();
 delete pa2;
}
FuncA called
FuncBB called
FuncA called
FuncB called

B  b; 

 A  *pa;

 pa = &b;

 A *pa2 = newA;

 pa->FuncA(); ( 3)//pa=&b动态绑定但是FuncA不是虚函数,所以FuncA called

 pa->FuncB(); ( 4)//FuncB是虚函数所以调用B中FuncB,FuncBB called  

 pa2->FuncA(); ( 5)//pa2是A类指针,不涉及虚函数,调用的都是A中函数,所以FuncA called FuncB called

 pa2->FuncB()

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值