C++面试基础知识整理(4)

面向对象

封装

  • public 成员:可以被任意实体访问
  • protected 成员:只允许被子类及本类的成员函数访问
  • private 成员:只允许被本类的成员函数访问

问题

如何定义一个只能在堆上(栈上)生成对象的类?

  • 只能在堆上:

    • 方法:将析构函数设置为私有
    • 原因:C++ 是静态绑定语言,编译器管理栈上对象的生命周期,编译器在为类对象分配栈空间时,会先检查类的析构函数的访问性。若析构函数不可访问,则不能在栈上创建对象。
  • 只能在栈上

    • 方法:将 new 和 delete 重载为私有
    • 原因:在堆上生成对象,使用 new 关键词操作,其过程分为两阶段:第一阶段,使用 new 在堆上寻找可用内存,分配给对象;第二阶段,调用构造函数生成对象。将 new 操作设置为私有,那么第一阶段就无法完成,就不能够在堆上生成对象。

如何定义一个只能在堆上(栈上)生成对象的类?

继承

  • 基类(父类)——> 派生类(子类)

  • public继承:基类成员在派生类中的访问权限保持不变

  • private继承:基类所有成员在派生类中的访问权限都会变为私有(private)权限

  • protected继承:基类的共有成员(public)和保护成员(protected)在派生类中的访问权限都会变为保护(protected)权限,私有成员(private)在派生类中的访问权限仍然是私有(private)权限。

  • 基类成员权限 public继承 private继承 protected继承
    public public private protected
    private private private private
    protected protected private protected

多态

  • 是对于不同对象接收相同消息时产生不同的动作。
  • C++的多态性具体体现在编译和运行两个方面:
    • 在程序编译时多态性体现在函数和运算符的重载上,也叫静态多态、早绑定
    • 在程序运行时的多态性通过继承和虚函数来体现,也叫动态多态、晚绑定

构造函数

问题

复制构造函数中能否传值参数?

不可以,如果允许复制构造函数传值,则会在复制构造函数中调用复制构造函数,就会形成永无休止的递归调用从而导致栈溢出。

成员初始化列表作用及哪些情况必须使用

  • 更高效:少了一次调用默认构造函数的过程。
  • 有些场合必须要用初始化列表:
    1. 常量成员,因为常量只能初始化不能赋值,所以必须放在初始化列表里面
    2. 引用类型,引用必须在定义的时候初始化,并且不能重新赋值,所以也要写在初始化列表里面
    3. 没有默认构造函数的类类型,因为使用初始化列表可以不必调用默认构造函数来初始化,而是直接调用拷贝构造函数初始化。
  • 成员变量的初始化顺序只与他们在类中声明的顺序有关,而与在初始化列表中的顺序无关。
class A
{
    
    
private:
    int n1;
    int n2;
public:
    A():n2(0),n1(n2+2){
    
    }
    void Print()
    {
    
    
        cout<<n1<<" "<<n2<<end;
    }
};
int main()
{
    
    
    A a;
    a.Print();
    return 0;
}

上面代码的输出

n1先于n2被声明,因此n1也会在n2之前被初始化,所以会先用n2+2去初始化n1,由于n2这时候还没有被初始化,因此它的值是随机的。同理,n1的值也是随机的,之后又用0初始化n2,因此,最终n2的值是0.

构造函数和析构函数的执行顺序

class A
{
    
    
public:
	A(){
    
    cout << "Construct A" << endl;}
	~A(){
    
    cout << "Destruct A" << endl;}
};
 
class C
{
    
    
public:
	C(){
    
    cout << "Construct C" << endl;}
	~C(){
    
    cout << "Destruct C" << endl;}
	
};
 
//Notice: C is a virtual public
class B: public A, public virtual C
{
    
    
public:
	B(): a(A()), c(C()) {
    
    cout << "Construct B" << endl;}
	~B(){
    
    cout << "Destruct B" << endl;}
	C c;
	A a;
};
 
int main(int argc, char const *argv[])
{
    
    
	B b;
	return 0;
}
  • 输出:
    Construct C
    Construct A
    Construct C
    Construct A
    Construct B
    Destruct B
    Destruct A
    Destruct C
    Destruct A
    Destruct C
  • 在类被构造的时候,先执行虚拟继承的父类的构造函数,然后从左到右执行普通继承的父类的构造函数,然后按照定义的顺序执行对象成员的初始化,最后是自身的构造函数的调用。析构函数与之完全相反,互成镜像。
  • 虚拟继承 > (从左到右)普通继承 > (按定义顺序)对象成员 > 自身
  • 初始化列表中的初始化顺序按照定义的顺序初始化。

对象成员与对象成员指针

  • 类被实例化时,先实例化作为成员的对象,再实例化该类;销毁时顺序正好相反。

使用

class Line
{
    
    
public:
	Coordinate m_CoorA;// 对象成员
	Coordinate *m_pCoorA;// 对象成员指针
}

this指针

  • this 指针是一个隐含于每一个非静态成员函数中的特殊指针。它指向调用该成员函数的那个对象。
  • 当对一个对象调用成员函数时,编译程序先将对象的地址赋给 this 指针,然后调用成员函数,每次成员函数存取数据成员时,都隐含使用 this 指针。

使用

 class Array
    {
    
    
    public:
    	Array(T *this, int _len){
    
     this->len = _len;}// this指针作为每一个成员函数的隐含参数
        int getLen(T *this){
    
     return this->len;}
        vois setLen(T *this, int _len){
    
     this->len = _len;}
        
        Array& printInfo()// 注意返回引用
        {
    
    
            cout<<len<<endl;
        	return *this;// 返回this指针,可以实现对象的链式引用
        }
    private:
        int len;
    }
    
    int main(){
    
    
        Array arr1(10);
        arr1.printInfo().setLen(5);// 对象的链式引用
        cout<<arr1.getLen()<<endl;
        return 0;
    }

深拷贝与浅拷贝

class Array
{
    
    
public:
    Array()
    {
    
    
        m_iCount=5;
        m_pArr=new int[m_iCount];
    }
    // 浅拷贝
    Array(const Array& arr)
    {
    
    
        m_iCount=arr.m_iCount;
        m_pArr=arr.m_pArr; // 只拷贝了指针,使得两个指针指向同一个地址。1、在调用析构函数时会delete一块内存两次,造成程序崩溃。2、任何一方的改动都会影响另一方。
    }
    // 深拷贝
    Array(const Array& arr)
    {
    
    
        m_iCount=arr.m_iCount;
        m_pArr=new int[m_iCount];
        for(int i=0;i<m_iCount;i++){
    
    
            m_pArr[i]=arr.m_pArr[i];// 将堆中内存的数据也进行拷贝
        }
    }
private:
    int m_iCount;
    int *m_pArr; // 注意:数据成员是指针
}

猜你喜欢

转载自blog.csdn.net/qq_34731182/article/details/113420825