【笔试题】【day13】

目录

第一题(正确的个数)

第二题(父子类指针的释放)

第三题(重载)

第四题(拷贝构造)

第五题(多态的调用条件)


第一题(正确的个数)

下列描述,正确的一共有多少个()
1)const char *p,这是一个常量指针,p的值不可修改
2)在64位机上,char *p= “abcdefghijk”; sizeof(p)大小为12
3)inline会检查函数参数,所以调用开销显著大于宏
4)重载是编译时确定的,虚函数是运行时绑定的

A 1
B 2
C 3
D 4

A:p是可以修改的,只是p所指的值不能被修改,因为const锁定的是*p,也就是p指向的内容

B:只要p是一个指针,在32位上是4个字节,64位上为8字节

C:宏会展开,内联函数同样会展开,其实是差不多的

D:重载是静态编译,虚函数是我们多态,也就是动态绑定,是对的

第二题(父子类指针的释放)

 C++将父类的析构函数定义为虚函数,下列正确的是哪个()

A 释放父类指针时能正确释放子类对象
B 释放子类指针时能正确释放父类对象
C 这样做是错误的
D 以上全错

我们申请一个子类对象,这个子类对象会包含一个父类对象。

我们将这个子类对象的地址赋给一个父类的指针。

当我们去释放父类的指针的时候,它只会去释放父类的那一部分的空间,子类独有的那一部分并不会去释放。

class A
{
public:
    A(){
        cout<<"A()"<<endl;
    }

    ~A()
    {
        cout<<"~A()"<<endl;
    };

};

class B :public A
{
public:
    B(){
        cout<<"B()"<<endl;
    }

    ~B() {
        cout << "~B()" << endl;
    }
};
int main()
{
    A *a1=new B;
    delete a1;
    return 0;
}

这里我们观察到构造函数和析构函数的个数时不一样的。

 但是当我们将这个父类的析构函数定义成虚函数之后

class A
{
public:
    A(){
        cout<<"A()"<<endl;
    }

    virtual ~A()
    {
        cout<<"~A()"<<endl;
    };

};

class B :public A
{
public:
    B(){
        cout<<"B()"<<endl;
    }

    ~B() {
        cout << "~B()" << endl;
    }
};
int main()
{
    A *a1=new B;
    delete a1;
    return 0;
}

它在析构的时候就能够动态地去调用子类的析构函数,所以这样我们的子类的内容也能够被成功释放。

 

A

第三题(重载)

下列关于多态性说法不正确的是( )

A 多态性是指同名函数对应多种不同的实现
B 重载方式仅有函数重载
C 重载方式包含函数重载和运算符重载
D 多态性表现为静态和动态两种方式

B:重载除了函数的重载,还有运算符的重载

D:重载就是静态的多态,真正的多态是在运行时去决议的。

第四题(拷贝构造)

分析一下这段程序的输出

#include<iostream>
using namespace std;
class B
{
public:
    B()
    {
        cout << "default constructor" << " ";
    } 
    ~B()
    {
        cout << "destructed" << " ";
    }
    B(int i): data(i)
    {
        cout << "constructed by parameter" << data << " ";
    }
private: int data;
};
B Play( B b)
{
    return b;
}
int main(int argc, char *argv[])
{
    B temp = Play(5);
    return 0;
}

A constructed by parameter5 destructed destructed
B constructed by parameter5 destructed
C default constructor" constructed by parameter5 destructed
D default constructor" constructed by parameter5 destructed destructed 

这里我们的Play(5)中的5会发生隐式类型转换,转换成一个B的对象,也就是调用下面这个函数

所以会直接先打印出constructed by parameter5

然后这个B的对象会被拷贝给Play(B b),生成一个临时对象,b,然后这个临时对象被返回,再发生一次拷贝构造给temp。

但是由于编译器的优化,我们的编译器就直接键给这个返回的临时对象作为了我们的temp,所以就少了一次拷贝构造。

当我们这里的临时对象完成了对temp的拷贝之后,我们的临时对象就会进行析构,所以会打印一次destructed

最后我们的temp在程序运行完成之后,也会发生析构,再次打印destructed

A

第五题(多态的调用条件)

求输出结果

#include <iostream>
using namespace std;
class A
{
public:
    virtual void print()
    {
        cout << "A::print()" << "\n";
    }
};
class B: public A
{
public: virtual void print()
    {
        cout << "B::print()" << "\n";
    }
};
class C: public A
{
public: virtual void print()
    {
        cout << "C::print()" << "\n";
    }
};
void print(A a)
{
    a.print();
}
int main()
{
    A a, *aa, *ab, *ac;
    B b;
    C c;
    aa = &a;
    ab = &b;
    ac = &c;
    a.print();
    b.print();
    c.print();
    aa->print();
    ab->print();
    ac->print();
    print(a);
    print(b);
    print(c);
}

A C::print() B::print() A::print() A::print() B::print() C::print() A::print() A::print() A::print()
B A::print() B::print() C::print() A::print() B::print() C::print() A::print() A::print() A::print()
C A::print() B::print() C::print() A::print() B::print() C::print() B::print() B::print() B::print()
D C::print() B::print() A::print() A::print() B::print() C::print() C::print() C::print() C::print()

通过对象访问,只要是通过对象访问,就是静态绑定,也就是在编译时期,abc要调用的函数就已经确定了,和多态没有关系。

a.print();
b.print();
c.print();

多态,构成父子指针的关系

父类的三个指针,指向a,b,c也就是构成多态,所以会调用各自不同的函数

aa->print();

ab->print();

ac->print();

调动外部的全局函数,构造生成一个父类对象,无论你是哪一个子类对象,调用的就是父类函数。

print(a);

print(b);

print(c);

B

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

桜キャンドル淵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值