笔试被鄙视之细节问题二

探讨一下派生,基类指针问题,这可是笔试原题,自己分析下会是什么结果。

class A{

public:
    virtual void printll()
    {
        cout<<"A::print"<<endl;
    }
};
class B:public A
{
public:
    virtual void printll()
    {
        cout<<"B::print"<<endl;
    }
};
class C:public B
{
public:
    virtual void printll()
    {
        cout<<"C::print"<<endl;
    }
};
void printll(A a)
{
    a.printll();
}
void main()
{
    A a,*pa,*pb,*pc;
    B b;
    C c;
    a.printll();
    b.printll();
    c.printll();

    pa=&a;
    pb=&b;
    pc=&c;
    pa->printll();
    pb->printll();
    pc->printll();

    printll(a);
    printll(b);
    printll(c);

}

如果全答对了,请飘过,模棱两可的还是看看下面我的分析吧。

首先看main中第一行  A a,*pa,*pb,*pc;一定要注意pa,pb,pc都是基类A的指针。

    a.printll();                                                     A::print
    b.printll();                                                     B::print
    c.printll();这三个都是直接由ABC创建的对象,输出的结果也都必然是  C::print ,有没有人这三项结果都为C::print,这就是误认为b,c有指向子类的作用,这个作用是指针才有的,并且是基类指针指向派生类对象时才生效。

先说下派生类内存布局,派生类对象的内存布局上首先是基类的数据,然后才是自己的数据,调用基类的函数时,如果自己重写了就调用自己的。

再看第二问,pa,pb,pc都有了值,pa指向自身,pb指向的内存布局到b,但包含了a中的数据,pc指向的内存到c,但包含了a,b中的数据,故可得结果

A::print

B::print

C::print

再看全局函数printll(A a),参数是基类对象,如果传递的是派生类对象,那对不起了,需要把你截断了,相当于在b(以b为例)的内存布局中找到自己的数据,把多余的数据丢弃,这是C++内部的隐式转换,需要注意。这样大家也知道输出结果是什么了吧。

最后如果我这样改动程序中两处,会是什么结果呢

void printll(A* a)
{
    a->printll();
}

printll(&a);
printll(&b);
printll(&c);



 

posted @ 2013-07-20 18:01  坚固66  阅读(195)  评论(0编辑  收藏  举报