虚函数的问题

vcgaoshou 2012-07-17 09:31:25
实现运行时多态的条件不同的教材上有不同的表述
例1.
(1)类之间符合类型兼容规则
(2)必须声明是虚函数
(3)必须通过成员函数或基类指针,引用调用虚函数
例2
(1)类之间符合类型兼容规则
(2)派生类必须公有继承基类,必须是虚函数
(3)必须通过基类指针,引用调用
问题是,
(1)那种表述是正确的
(2)类型兼容规则我知道,但“类之间符合类型兼容规则”在这里的具体含义是什么?
(3)“通过成员函数调用虚函数”,如果这个成员函数通过对象调用,成员函数再调用虚函数,还是运行时多态吗?肯定不是啊,因此这句话该怎么理解?
...全文
143 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
DBFNO 2012-07-18
  • 打赏
  • 举报
回复
C++primer是这样说的:
1)只有指定为虚函数的成员才能进行动态绑定,成员函数默认为非虚函数,非虚函数不进行动态绑定

2)必须通过基类类型的引用或指针进行函数调用。


class A{
public:
virtual f(){}
virtual f2(A&item);
{
//process code
}
};

calss B:public A{
public:
virtual f(){}
virtual f2(A&item)
{
//process code
}
};

指针
A a;
A *p = new B;
p->f() //调用B中的f(); 根据其运行时的类型,确定执行哪个作用域中的函数;
p = &a;
p->f() //调用A中的f()

引用
f3(const A&item)
{
item.f2();
}
A a; B b;
f3(a) //A 中的f2()函数
f3(b) //B中的f2()函数
pathuang68 2012-07-17
  • 打赏
  • 举报
回复
(1) 严格点,两种说法都不够全面。关于这个问题,楼主可以看C++ Primer Plus或者C++ Primer就会很清楚

(2) “类之间符合类型兼容规则”通常是指类和类之间有继承关系,这样才能做到类型间的转换,否则不可以。
另外需要提醒的,从派生类转型到基类,总是安全的,这种转换叫向上转型(up-casting),反之是向下转
型,向下转型则未必是安全的。关于这个问题,看Inside C++ Object Model就会很清楚。

(3) “通过成员函数调用虚函数”这种说法至少是不够严谨的,没有必要通过其他的成员函数去调用虚函数,纯
属多此一举。在调用虚函数时,调用的是动态类型中实现的虚函数,比如:
Base* pb = new Derived;
pb->some_virtual_function();
这个pb的静态类型是Base*, 其动态类型则是Derived,所以上面的调用就是调用Derived中实现的虚函数
some_virtual_function(),而不是Base中实现的。
拿枪的大盖伦 2012-07-17
  • 打赏
  • 举报
回复
我猜是有的教材比较不好了 楼主应该看些像c++primer等经典著作 这样即便有问题了 也好有人问
丈八涯 2012-07-17
  • 打赏
  • 举报
回复
(2)估计还是说子类属于基类。
(3)类中基类的成员函数调用虚函数,子类对象中,该成员函数已经是子类对象的成员函数了。使用基类的指针调用这个成员函数,最终还是会调用到子类的东东。也还是运行时多态。

class a
{
virtual void fun1()
{
cout<<"a"<<endl;
};
public:
void fun()
{
fun1();
}
};

class b:public a
{
void fun1()
{
cout<<"b"<<endl;
}
};

int main()
{
a *p;
p = new b();
p->fun();
return 0;
}

静c心 2012-07-17
  • 打赏
  • 举报
回复
如果不加vitual,子类的部分,不会析构
vcgaoshou 2012-07-17
  • 打赏
  • 举报
回复
6楼注意,q=b是错误的语句
2012-07-17
  • 打赏
  • 举报
回复
最后还是会输出 class A!!!
2012-07-17
  • 打赏
  • 举报
回复
真心不明白通过成员函数访问虚函数有什么意义?

刚刚测试了下,引用好像不起作用啊。
有人解释下嘛。

#include<iostream>


using namespace std;

class A
{
public:
void moreprint()
{
print();
}
virtual void print()
{
cout<<"class A:"<<endl;
}
};

class B:public A
{
public:
void print()
{
cout<<"class B:"<<endl;
}
};

int main()
{
A a;
B b;
a.print();
b.print();

A* p;
p=&a;
cout<<"基类指针调用基类对象:"<<endl;
p->print();


cout<<"基类指针调用子类对象:"<<endl;
p=&b;
p->print();


A& q=a;

cout<<"基类引用调用基类对象:"<<endl;

q.print();

cout<<"基类引用调用子类对象:"<<endl;
q=b;
q.print();

return 0;
}
W170532934 2012-07-17
  • 打赏
  • 举报
回复
3楼讲解的不错
sadgod 2012-07-17
  • 打赏
  • 举报
回复
楼上说的清晰明白,赞一个~

64,650

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧