首页 > 试题广场 >

下面程序的输出是?

[单选题]
下面程序的输出是()
class A
{
public:
    void foo()
    {
        printf("1");
    }
    virtual void fun()
    {
        printf("2");
    }
};
class B: public A
{
public:
    void foo()
    {
        printf("3");
    }
    void fun()
    {
        printf("4");
    }
};
int main(void)
{
    A a;
    B b;
    A *p = &a;
    p->foo();
    p->fun();
    p = &b;
    p->foo();
    p->fun();
    A *ptr = (A *)&b;
    ptr->foo();
        ptr->fun();
    return 0;
}
  • 121434
  • 121414
  • 121232
  • 123434
指针p是类A的指针,而A类是B类的父类。使用p指针指向B类时,一般情况下同名成员都会指向它的父类元素的成员。而使用virtural关键字能指定成员函数为虚函数,这样父类的指针能引用到子类的同名函数。
发表于 2020-08-24 11:41:31 回复(0)
即使对子类进行类型强转,还是父类指针指向子类对象
发表于 2020-09-02 15:19:46 回复(0)
    这个题考察的知识点挺细的,做错的同学应该都是以为第三个函数调用调用的是B类的foo函数,其实不然,C++Primer第五版549页里面有一段关于函数调用的解析过程的解释:假设我们的调用是p->mem(),通过指针调用成员函数,或者obj.mem(),通过对象调用成员函数,编译器会做以下事情。1.首先确认p或obj的静态类型,编译器会首先在静态类型对应的类中寻找名为mem的成员函数(注意,编译器只是判断函数名字是否相同,而不管参数),如果没找到,就依次在直接基类中寻找,直到继承链的顶端,如果没找到,编译器就会报错,如果找到了,就到第二步。2.如果找到了这个成员函数,首先进行类型检查,判断调用是否合法,如果合法,就跳到第三步。3.如果这个函数是虚函数并且我们是通过指针或者引用调用的,那么就会根据对象的动态类型来判断调用虚函数的哪一个版本,如果不是虚函数或者我们是通过对象调用的,那么就执行常规的函数调用。
    所以,按照上面的规则,第二个p->foo(),p的静态类型是A*,所以按照第一步,现在A类中查找是否有foo函数,显然A类中有,第二步,也满足合法调用,第三步,由于foo不是虚函数,所以只是普通的函数调用,所以总结下来就是调用的A类的foo函数。
发表于 2022-03-22 23:10:04 回复(0)
基类中某个函数用virtual声明为虚函数,派生类中和此函数同名但没有virtual声明的函数也还是虚函数,在派生类的定义中也会重写基类的那个虚函数。
发表于 2021-11-29 17:27:06 回复(0)