鄙人愚笨,看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() ,并且还是虚拟的。虚拟函数可以继承,实至名归。