问题
I have a problem in virtual function: Here is some code as an example:
class A
{
public : virtual void print(void)
{
cout<< "A::print()"<<endl;
}
};
class B : public A
{
public : virtual void print(void)
{
cout<<"B::print()"<<endl;
}
};
class C : public A
{
public : void print(void)
{
cout<<"C::print()"<<endl;
}
};
int main(void)
{
A a,*pa,*pb,*pc;
B b;
C c;
pa=&a;
pb=&b;
pc=&c;
pa->print();
pb->print();
pc->print();
a=b;
a.print();
return 0;
}
the result: A::print() B::print() C::print() A::print()
I know it's a Polymorphism ,and know have a table called virtual-function-table,but I don't know how it is to achieve,And
a=b;
a.print();
the result is: A::print() not B::print(),why it hasn't polymorphism. thank you!
回答1:
a=b;
a.print();
It will print A::print()
because a=b
causes object-slicing, which means a
gets only the a-subobject of b
. Read this :
- What is object slicing? .
Note that runtime-polymorphism can be achieved only through pointer and reference types. In the above code, a
is neither pointer, nor reference type:
A * ptr = &b; //syntax : * on LHS, & on RHS
A & ref = b; //syntax : & on LHS, that is it!
ptr->print(); //will call B::print() (which you've already seen)
ref.print(); //will call B::print() (which you've not seen yet)
回答2:
The object a
is still of type A
. The assignment only copies data from b
, it doesn't make a
a B
object.
This is called object slicing.
回答3:
Because a
is not a pointer. It is an instance of A
, and the assignment a=b;
copies the instance of b
to a
. But the function call is on an instance of A
.
回答4:
When you do a = b;
you b
object is sliced i.e. only the A
part of it gets copied. Polymorphism only works through pointers and references. Search "object slicing" to learn about the subject.
回答5:
To learn more about virtual method table please see wiki. But in general case the table keeps the information methods' addresses. So, class A in the table will have one record says that method print is in address X. When you do pa=&b class B simply replace the table to its one in such a way that address of method print will point to address Y.
But when you do a=b you copy object. In this case polymorphism doesn't work.
回答6:
After a call to any member function on a object of type A
, you still have A
object (except an explicit destructor call, which leaves nothing at all).
a = b;
The assignment of a class instance is just a call to a particular member function called "operator=
". There is nothing special with "operator=
" here, except its name is standard. You could use another name for assignment:
a = b;
// you could as well write:
a.assign(b);
// (if such member was defined)
Just as you could write add(a,b)
instead of a+b
, but a+b
is more readable.
An explicit call to a function never changes the type of the variable it is called on:
A a;
foo(a);
// a is still a A
a.bar();
// a is still a A
The declared type of a
is A
, and cannot be changed to something else: this is an invariant of a
.
This is also true for pointers: a variable of type pointer to A
will always have the type pointer to A
:
void foo (A*&);
A *bar();
A a;
A *p = &a;
foo (p); // might change p
// a still has type: pointer to A
p = bar();
// a still has type: pointer to A
But p
might point to an object of type B
, so, at runtime, the dynamic type of *p
will be B
; but the dynamic type of p
is always A*
.
来源:https://stackoverflow.com/questions/11718070/dynamic-binding-in-c-on-copied-object