再谈虚函数

这几天看C++的一些基础知识发现对虚函数之前理解一直不太清楚,这里记录几点

 

1) typeid的使用

 

   B  * p;//父类
   D ob;//B类的子类
    p =& ob;//父类指针指向子类对象
 当父类中有虚函数功能,子类实现了这个虚函数的时候:
    typeid( * p).name() -----得出结果是 class D

    typeid(p).name()----得出结论是 classs (B *)
        cout << " typeid(p)==typeid(B*) " << endl;
 cout << typeid(p->fun()).name();//输出函数返回值类型

------------------------------------------------------------------

class One

{
    class Nested {}; //在类中又定义了一个类
    Nested* n;

    public:  

        One() : n(new Nested)

        {}

       ~One()

        {

                delete n;

        }

    Nested* nested()//类 One的函数

    {

             return n;

      }

};
主应用程序中调用:

One o;   
cout << typeid(*o.nested()).name() << endl;//-------会输出:Class One::Nest  (注意输出形式)

(如果nest类不是在One中定义,而是在外部进行定义,则这句会输出 Class Nest)

————————————————————————————————————————————————

2)是调用父类函数还是子类函数?

B 父类 有个虚函数fun()

D子类   实现了虚函数fun()

   B  * p;//父类
   D ob;//B类的子类
    p =& ob;//父类指针指向子类对象

    p->fun();//此时因为父类函数是虚

    函数,会调用子类的fun(),而不是父类。(多态就是因此实现的吧?)

 

B 父类 函数fun()(这里不是虚函数)

D子类   继承函数fun()

   B  * p;//父类
   D ob;//B类的子类
    p =& ob;//父类指针指向子类对象

    p->fun();//此时因为父类函数不是虚

    函数,会调用父类的fun(),而不是子类。

————————————————————————————————————————————————

3)虚函数和析构函数

之前在 effective C++ 编程中就读到过父类的析构函数要是虚函数,一直不太理解

写到程序里运行试了一下:

class CParent
{
  public:
   CParent()
   {
    cout<<"parent create   ";
   }
   virtual ~CParent(){ cout<<"Parent Destroy    ";}
  private:
   char *m_pcData;
};
 
class CChild : public CParent
{
  public:
   CChild()
   {
   cout<<"Child create     ";
   }
    ~CChild(){cout<<"Child Destroy   ";}
  private:
   char *m_piValue;
};

 

在主函数中调用:

   CParent  *pParent;
  pParent = new CChild;

  delete pParent;//这里这样删除是没有问题的

程序运行依次为:调用CParent,调用CChild,调用~CCChild,调用~CParent。

 

但是如果在父类的析构函数中没有virtual关键字可就大不一样了

程序依次运行:调用CParent,调用CChild,调用~CCChild。

这里并没有调用~CParent,因为建立的父类对象没有被虚构,这样就造成了内存的泄漏!!

 

4)虚函数和参数和默认参数

已知类实现如下:

enum ShapeColor{RED, GREEN, BLUE};

 

一个表示几何形状的类

class Shape {

public:

                                                                     

                                                                      virtual void Draw(ShapeColor color = RED) = 0;

                                                                     

};

 

class Rectangle : public Shape {

public:

                                                                     

                                                                       virtual void Draw(ShapeColor color = GREEN);

                                                                     

};

 

class Circle : public Shape {

public:

                                                                     

                                                                      virtual void Draw(ShapeColor color );

                                                                     

};

 

…..

Shape      *pc= new Circle;

Shape      *pr = new Rectangle;

 

pc->Draw();  //  pc->Draw() 实现是Circle:draw(RED),

pr->Draw();      //     

pr->Draw()实现Rectangle:draw(RED);

特别注意这里的参数用的可是Shape类的默认参数RED

 

 

 

——————————————————————————————————

 

class CParent {

       public:

              ......

              virtual int WhoLikeThisGame(int x);

       private:

              char *m_pcData;

};

 

int CParent::WhoLikeThisGame (int x)

{

       ......

       Cout<<”Parent Like This Game”;

       ......

}

 

class CChild : public CParent {

       public:

              ......

              virtual int WhoLikeThisGame(char c);

       private:

              char *m_piValue;

};

......

 

int CChild:: WhoLikeThisGame (char c)

{

       ......

       Cout<<”Child Likes This Game”;

       ......

}

      ……

      CParent  *pParent;

              pParent = new CChild;

              pParent-> WhoLikeThisGame(10);//这里输出的是:

                                                                        Parent Like This Game         

            因为父类和子类定义的函数参数类型不一样,所以会被认为是重新定义了,并不是被继承了。

因此一定要多注意virtual的用法。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C的虚函数是通过在基中声明一个虚函数,然后在派生中对其进行重写来实现的。虚函数的引入对于C大型项目的接口设计和统一标准起到了非常重要的作用。虚函数的另一个重要特性是多态性,它可以实现动态联编,即在运行时确定函数的调用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [C++虚函数与纯虚函数](https://blog.csdn.net/wx_14678/article/details/103844354)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [38.【C++ 虚函数虚函数 虚基 (最全详解)】](https://blog.csdn.net/qq_69683957/article/details/126397761)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [C++纯虚函数浅谈](https://blog.csdn.net/duwenchao_Tom/article/details/76647380)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值