【笔试题】【day16】

发布于:2022-10-29 ⋅ 阅读:(437) ⋅ 点赞:(0)

目录

第一题(虚表指针的位置)

第二题(私有继承的权限问题)

第三题(运行时多态和编译时多态)

第四题(多态的条件)

第五题(多态+32位下指针大小)


第一题(虚表指针的位置)

代码执行后,a和b的值分别为?

#include <iostream>

using namespace std;
class Test{
public:
    int a;
    int b;
    virtual void fun() {}
    Test(int temp1 = 0, int temp2 = 0)
    {
        a=temp1 ;
        b=temp2 ;
    }
    int getA()
    {
        return a;
    }
    int getB()
    {
        return b;
    }
};
int main()
{
    Test obj(5, 10);
// Changing a and b
    int* pInt = (int*)&obj;
    *(pInt+0) = 100;
    *(pInt+1) = 200;
    cout << "a = " << obj.getA() << endl;
    cout << "b = " << obj.getB() << endl;
    return 0;
}

A 200 10
B 5 10
C 100 200
D 100 10

首先我们创建了一个Test类型的对象,然后将其地址强制转换成int*赋值给了pInt,也就是得到了起始位置的4个字节的地址(32)位

如果没有虚函数的话,也就是将下面这行代码注释掉

 

我们的a和b刚好是在我们的对象前面的两个成员,

所以*(pInt+0)其实就是我们的a的值,我们将其修改为100

*(pInt+1)其实就是我们的b的值,我们将其修改为200

但是有了这里的虚函数的话

我们的对象的首位置是我们的虚表指针

然后+1之后的修改,实际上修改的是我们的a成员

也就是我们这里将我们的虚表赋值为了100,然后将我们的a成员赋值为了200

然后我们的b成员还是原来的10

由于这里没有访问虚函数,所以没有报错,但实际上如果通过多态访问虚函数表,就会报错,因为我们的虚表指针已经不能找到我们正确的虚表了 

A

第二题(私有继承的权限问题)

下列程序的输出结果:

#include <iostream>
using namespace std;
class A
{ 
public:
    void print()
    {
        cout << "A:print()";
    }
};
class B: private A
{ 
public:
    void print()
    {
        cout << "B:print()";
    }
};
class C: public B
{ 
public:
    void print()
    {
        A:: print();
    }
};
int main()
{   
    C b;
    b.print();
}

A A:print()
B B:print()
C 编译出错

B继承A,但是一个私有继承

C共有继承B

我们这里创建了一个C的对象,想要去调用A的方法

程序会出错,因为B私有继承A,那么A中的所用成员在B中表现为私有成员

那我们的C类是B类的子类,子类没有办法访问父类的私有成员。 

C

第三题(运行时多态和编译时多态)

下面关于多态性的描述,错误的是() 

A C++语言的多态性分为编译时的多态性和运行时的多态性
B 编译时的多态性可通过函数重载实现
C 运行时的多态性可通过模板和虚函数实现
D 实现运行时多态性的机制称为动态绑定

C中的模板和多态没有关系,模板是为了实现泛型编程,这两个不是同一个机制

C

第四题(多态的条件)

写出下面程序的输出结果

#include <iostream>
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;
}

A FuncA called FuncB called FuncA called FuncB called
B FuncA called FuncBB called FuncA called FuncB called
C FuncA called FuncBB called FuncAB called FuncBB called
D FuncAB called FuncBB called FuncA called FuncB called

创建一个子类对象b

父类指针指向子类对象pa

父类指针指向父类对象pa2

pa->FuncA()由于我们的pa是父类指针指向子类对象,但是父类的FuncA()中并没有写virtual,所以不满足多态的条件,直接调用父类的FuncA()方法,打印FuncA called

pa->FuncB()由于这里是父类的指针指向子类的对象并且父类中的FuncB前面有virtual,满足多态的条件,所以我们这里直接调用子类的FuncB,打印FuncBB called 

pa2->FuncA 这里的pa2是父类的指针指向父类的对象,所以它是直接调用父类的FuncA方法,打印FuncA called

 pa2->FuncB 这里的pa2是父类的指针指向父类的对象,不满足多态的条件,所以它是直接调用父类的FuncB方法,打印FuncB called

第五题(多态+32位下指针大小)

#include<iostream>
using namespace std;
class Base
{
public:
    virtual int foo(int x)
    {
        return x * 10;
    }
    int foo(char x[14])
    {
        return sizeof(x) + 10;
    }
};
class Derived: public Base
{
    int foo(int x)
    {
        return x * 20;
    }
    virtual int foo(char x[10])
    {
        return sizeof(x) + 20;
    }
} ;
int main()
{
    Derived stDerived;
    Base *pstBase = &stDerived;
    char x[10];
    printf("%d\n", pstBase->foo(100) + pstBase->foo(x));
    return 0;
}

 在32位环境下,以上程序的输出结果是?

A 2000
B 2004
C 2014
D 2024

我们首先创建了一个子类对象,然后用父类的指针指向子类的对象

父类的指针访问foo(100),这里满足了多态调用的条件,调用的是子类的方法,也就是我们下面两个中,更下面的这个方法

 

 100*20=2000

这里只要传入一个指针数组就可以调用这个方法,跟你是不是14没有关系

 

这里我们是父类的指针,并且不满足多态的条件,所以我们直接调用的就是父类的foo方法。因为我们在32位的系统下,我们的指针的大小为4个字节,所以这里返回的是

 4+10=14

最后我们将这两个值加起来也就是2000+14=2014 

C


网站公告

今日签到

点亮在社区的每一天
去签到