探讨一下派生,基类指针问题,这可是笔试原题,自己分析下会是什么结果。
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);