再论虚函数!

本文通过实例探讨了C++中虚函数的概念、继承、作用及如何在代码中使用虚函数,包括虚函数的继承特性、虚函数的调用过程、以及如何避免虚函数引起的警告等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

鄙人愚笨,看C++2月了 对于虚函数 还是不能深刻理解,今特写些东西,再学习一下。

程序:

#include"iostream"
using namespace std;
class A{
public:
 A(int i):a(i)  {cout<<"调用构造函数A "<<endl;}
 void showa(){cout<<a<<"haha"<<endl;}
 void showw(){cout<<"A::"<<endl;}//只有虚函数才能=0
  ~A(){cout<<"析构A"<<endl;};
protected:int a;

};

class B:public  A//virtual public A
{
public:B(int x,int y):A(x),j(y){cout<<"调用构造函数B "<<endl;}
 void showb(){cout<<a<<" "<<j<<endl;}
 void showw(){cout<<"B::"<<endl;}//删掉词句,也能输出C::,说明虚函数能继承哦
 ~B(){cout<<"析构B"<<endl;}
protected:int j;
};
class D
{
public:D(){cout<<"构造D"<<endl;}
    virtual void showd(){cout<<"d的值"<<endl;}
    void showw(){cout<<"D::"<<endl;}
    ~D(){cout<<"析构D";}

};

class C:public  B, public  A,public D//virtual public A

{
public:
    C(int x,int y,int z):B( x, y),A(y),k(z)

    {cout<<"调用构造函数C "<<endl;}
    void showc(){cout<<"B::a="<<B::a<<"  "<<"A::a="<<A::a<<"  "<<j<<"  "<<k<<endl;}
  void showw(){cout<<"C::"<<endl;}
  void showd(){cout<<"CD::"<<endl;}
  ~C(){cout<<"析构C";}
private:int k;

};
int main()
{
C c(1,2,3);
c.showw();
return 0;
}

四个类里面都有函数showw(),程序当然不会报错了,因为继承嘛。此程序的输出是C::,说明在没有指定域的情况下,默认的是派生类的函数哦!

当然有个警告: warning C4584: “C”: 基类“A”已是“B”的基类
1>        f:\c++\vs2008\asd\asd\adw.cpp(5) : 参见“A”的声明
1>        f:\c++\vs2008\asd\asd\adw.cpp(15) : 参见“B”的声明

我想:是因为A其实有两份拷贝,也就是A-B-C和A-C。我试了下把A定义成虚基类,也就是弄成一份拷贝,警告消失。具体见注释!

 

现在把基类A里的showw()弄成虚函数。如下

#include"iostream"
using namespace std;
class A{
public:
 A(int i):a(i)  {cout<<"调用构造函数A "<<endl;}
 void showa(){cout<<a<<"haha"<<endl;}
 virtual void showw(){cout<<"A::"<<endl;}//只有虚函数才能=0
  ~A(){cout<<"析构A"<<endl;};
protected:int a;

};

class B:public  A//virtual public A
{
public:B(int x,int y):A(x),j(y){cout<<"调用构造函数B "<<endl;}
 void showb(){cout<<a<<" "<<j<<endl;}
 void showw(){cout<<"B::"<<endl;}//删掉词句,也能输出C::,说明虚函数能继承哦
 ~B(){cout<<"析构B"<<endl;}
protected:int j;
};
class D
{
public:D(){cout<<"构造D"<<endl;}
    virtual void showd(){cout<<"d的值"<<endl;}
    void showw(){cout<<"D::"<<endl;}
    ~D(){cout<<"析构D";}

};

class C:public  B, public  A,public D//virtual public A

{
public:
    C(int x,int y,int z):B( x, y),A(y),k(z)

    {cout<<"调用构造函数C "<<endl;}
    void showc(){cout<<"B::a="<<B::a<<"  "<<"A::a="<<A::a<<"  "<<j<<"  "<<k<<endl;}
  void showw(){cout<<"C::"<<endl;}
  void showd(){cout<<"CD::"<<endl;}
  ~C(){cout<<"析构C";}
private:int k;

};
int main()
{
C c(1,2,3);
c.showw();
return 0;
}

main函数不变,输出一模一样,我的理解是:如果虚函数不利用派生类的引用或是地址,也就跟普通函数一样了,不知道正确否,反正调试程序,没发现异样!

把主函数变下:

int main()
{
C c(1,2,3);
A *a=&c;

a->showw();

  }根据结果,输出的是C的showw(),当然很容易理解,正是虚函数的意义嘛。也可以调用a->A::showw(),输出的就是A的showw().

再加句:a->showc();报错,原因很简单,此函数不是a的成员。

到此,我想大体虚函数的怎么用可能会一点点,而其真正的意义呢?读书求甚解。

 

把B类的showw()删了,运行

结果正常跟没删一样,因为B继承了A的showw(),还是用程序说话吧。

改写main

C c(1,2,3);

B *b=&c;

b->B::showw();//输出A::

b->showw();//输出C::

输出是C的showw() 说明了B确实继承了A 的showw() ,并且还是虚拟的。虚拟函数可以继承,实至名归。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值