博客看到http://blog.csdn.net/hackbuteer1/article/details/7475622借用博主文章的内容,再此谢过。
#include<iostream>
using namespace std;
class A
{
public:
void foo()
{
printf(“1\n”);
}
virtual void fun()
{
printf(“2\n”);
}
};
class B : public A
{
public:
void foo()
{
printf(“3\n”);
}
void fun()
{
printf(“4\n”);
}
};
int main(void)
{
A a;
B b;
A *p = &a;
p->foo();
p->fun();
p = &b;
p->foo();
p->fun();
return 0;
}
笔试的题目中还有一个另类测试方法。即
B *ptr = (B *)&a; ptr->foo(); ptr->fun();
问这两调用的输出结果。这是一个用子类的指针去指向一个强制转换为子类地址的基类对象。结果,这两句调用的输出结果是3,2。
并不是很理解这种用法,从原理上来解释,由于B是子类指针,虽然被赋予了基类对象地址,但是ptr->foo()在调用的时候,由于地址偏移量固定,偏移量是子类对象的偏移量,于是即使在指向了一个基类对象的情况下,还是调用到了子类的函数,虽然可能从始到终都没有子类对象的实例化出现。
而ptr->fun()的调用,可能还是原因是C++多态性的原因,由于指向的是一个基类对象,通过虚函数列表的引用,找到了基类中fun()函数的地址,因此调用了基类的函数。由此可见多态性的强大,可以适应各种变化,不论指针是基类的还是子类的,都能找到正确的实现方法。
博客上如此解释,但是本人还是不清楚,有哪位高手能再次详解么,谢啦
#include<iostream>
using namespace std;
class A
{
public:
void foo()
{
printf(“1\n”);
}
virtual void fun()
{
printf(“2\n”);
}
};
class B : public A
{
public:
void foo()
{
printf(“3\n”);
}
void fun()
{
printf(“4\n”);
}
};
int main(void)
{
A a;
B b;
A *p = &a;
p->foo();
p->fun();
p = &b;
p->foo();
p->fun();
return 0;
}
笔试的题目中还有一个另类测试方法。即
B *ptr = (B *)&a; ptr->foo(); ptr->fun();
问这两调用的输出结果。这是一个用子类的指针去指向一个强制转换为子类地址的基类对象。结果,这两句调用的输出结果是3,2。
并不是很理解这种用法,从原理上来解释,由于B是子类指针,虽然被赋予了基类对象地址,但是ptr->foo()在调用的时候,由于地址偏移量固定,偏移量是子类对象的偏移量,于是即使在指向了一个基类对象的情况下,还是调用到了子类的函数,虽然可能从始到终都没有子类对象的实例化出现。
而ptr->fun()的调用,可能还是原因是C++多态性的原因,由于指向的是一个基类对象,通过虚函数列表的引用,找到了基类中fun()函数的地址,因此调用了基类的函数。由此可见多态性的强大,可以适应各种变化,不论指针是基类的还是子类的,都能找到正确的实现方法。
博客上如此解释,但是本人还是不清楚,有哪位高手能再次详解么,谢啦
解决方案
5
这样想吧:foo()是非虚函数,所以申明的是什么类,调用的就是哪个类的foo
fun()是虚函数,所以不管申明的是什么类,调用的时候都是按照实际是什么类的fun执行
不过话说回来,也不要太纠结于这些,原因是实际代码中总会要求虚函数一定要加上virtual ,class B里面的fun这种前面不加visual的,简直就是混淆视听,拙劣的设计,一巴掌拍死
fun()是虚函数,所以不管申明的是什么类,调用的时候都是按照实际是什么类的fun执行
不过话说回来,也不要太纠结于这些,原因是实际代码中总会要求虚函数一定要加上virtual ,class B里面的fun这种前面不加visual的,简直就是混淆视听,拙劣的设计,一巴掌拍死
5
没有virtual修饰,什么类声明,就是哪个的实现
有virtual修饰,什么类构造,就是哪个的实现
有virtual修饰,什么类构造,就是哪个的实现
5
感觉那篇博客没说出原理,网上给你搜了篇
http://blog.csdn.net/justaipanda/article/details/8137435
假如lz刚开始学的话,不太建议一开始研究太深。
http://blog.csdn.net/justaipanda/article/details/8137435
假如lz刚开始学的话,不太建议一开始研究太深。
5
#include <iostream> #include <new> using namespace std ; struct A { int a ; virtual void set () = 0 ; } ; struct B :public A { void set () override { a = 12 ; } } ; void set (A &l) { l.a = 24 ; } int main () { char tmp[sizeof (A)] = {0} ; A &p = reinterpret_cast<A &> (tmp) ; void *const *&vptr = reinterpret_cast<void *const *&> (p) ; p.a = 6 ; cout << p.a << " " << vptr << endl ; new (&p) B () ; p.set () ; cout << p.a << " " << vptr << endl ; void (*const vptr0) (A &) = (void (*) (A &)) vptr[0] ; void *const nvptr[] = {set} ; vptr = nvptr ; p.set () ; cout << p.a << " " << vptr << endl ; vptr0 (p) ; cout << p.a << " " << vptr << endl ; return 0 ; }