CSDN博客

img hahu

遭遇C++基础问题 [2004年5月29日 18:33 ]

发表于2004/7/11 3:46:00  852人阅读

用VC++有一段时间了,却发现用VC这么久,C++其实没学到什么。基本的不能再基本了,真正用起来还有深有体会的感觉。

需要定义三个对象,一个基类A,另外两个A1,A2从这个基类派生。说起来也就是用不用Virtual的问题,很简单,或许是没有注意过,或许注意过,也像这次一样灵犀一动,也在不经意的时候就忘记了,要不是现在开始在Linux下面写程序,还不知道什么时候能在注意起来。写一写,或许下次我就能很快地想起了。其实,试一下也就出来了,不是吗?

class A
{
 CList m_lsPoint;
 virtual void AddPoint()
        {
  m_lsPoint.Add(CPoint(0,0));
 }
 CList m_lsPoint2;
 void AddPoint2()
        {
  m_lsPoint2.Add(CPoint(0,0));
 }
};
class A1:public A
{
 void AddPoint()
 {
  m_lsPoint.Add(CPoint(1,1));
 }
 void AddPoint2()
 {
  m_lsPoint2.Add(CPoint(1,1));
 }
};
上面基类A中两个AddPoint的区别是一个有virtual,一个没有。测试代码如下:

 A1 *a1=new A1;
  ((A*)a1)->AddPoint();
 ((A*)a1)->AddPoint2();

上面两个函数的调用方法一样,可是最后查看m_lsPoint和m_lsPoint2的列表却发现加进去的点是不一样的m_lsPoint的点是(1,1),而m_lsPoint2的点是(0,0)。对此,作如下感想:

1.virtual修饰的是虚函数,顾名思义是从他派生出来以后,基类的这个函数就不再创建出来。A的AddPoint函数。AddPoint2没有用virtual修饰,虽然在直接调用a1->AddPoint2()的时候,并不执行a->AddPoint2(),但是,可以通过指针转换,来得到实际上存在的A类的AddPoint2函数。

2.A1从A派生,即A1具有了A的所有属性,比如一个学生的班级,学号属性在A中,A1中包含了他的各门功课成绩。要更新该学生的班级或者学号,但是实际上获得的信息只有A类的成员(班级,学号),如果直接从A1更新(即连同各成绩),必然会产生错误。这时候,需要的是不使用virtual关键字的基类。结构如下:

                                    |-班级
          | ——学生——|
          |                         |-学号
学生  |
信息  |——语文成绩
          |——数学成绩
          |——。。。
3.在用VC的时候经常也会用到virtual关键字,不过常常是直接在继承的时候用这种方法。比如

 void A1::AddPoint()
 {
  A::AddPoint();
  m_lsPoint.Add(CPoint(0,0));
 }

这种方法就变成了上面说到的那样,一次把基类,派生类的属性(成员)都更新了。但是,如果基类不是Virtual这样做就没有用了。想到,要是在A1::AddPoint2中也像这样加上父类的函数又没效呢?发现没效,再用这样((A*)this)->AddPoint2();也同样无用。这下我就不懂了。世上我不懂的事情太多了。

VC中的OnDraw,OnPaint之类的函数,也是virtual,却不调用基类的函数。按照1的思考,基类的这些函数就不用创建出来,也就节省了内存。是吗?不是吗?

晕!一直都在用MFC,根本不用去考虑类的结构,布局,一切按照微软布下的模板走路。真是失败,也该学学自己走路了。基类的结构真得很重要,就做类似上面那样的几个类,当然派生出来的不只有A1一个,却因为基类定义得太差,想改,却是别人写的,而且他是老员工,失败。派生类我在用,为了多几个接口,连本该基类写的东西,也放到派生类写了(屡次要求无效)。所谓面对对象的程序,实在郁闷。

这次在Unix下面做程序,才有以上遭遇,学学Linux,Unix,VI,有新事物出现,我又有动力了。

我。。。还。。。活着!

0 0

相关博文

我的热门文章

img
取 消
img