您的位置:首页 > 编程语言 > C语言/C++

自己对C++虚函数使用的深刻体会,以及覆写,重载的区别?

2008-10-27 16:40 260 查看
虚函数就是实现函数的覆写,

它们以下特点:

(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual关键字

还有,要注意一点,函数的返回值是影响不了覆写和重载函数的.

我的以下程序,思路 不对的地方就是没能完全理解多态的应用,

#include <iostream>
#include <vector>
#include <string>
using namespace std;

class A
{

};

class BA: public A
{
public:
int m_i;
int getValue()
{
return m_i;
}
};

class CA: public A
{
public:
string m_str;
string getValue()
{
return m_str;
}
};

class DA : public A
{
public:
vector <A *> m_vec;
};

int main()
{
BA *pBa = new BA;
pBa->m_i = 100;

CA *pCa = new CA;
pCa->m_str = "myprogram";

DA da;
da.m_vec.push_back(pBa);
da.m_vec.push_back(pCa);

//请问一下,我要在这里输出da.m_vec的所有内容,应该如何实现呢?

vector<A *> :: iterator it;

for (it = da.m_vec.begin(); it != da.m_vec.end(); it++)

{

(*it)->getValue(); // error,其类A没有该虚函数实现.

}

return 0;
}
在以上程序中, CA的string getValue()函数和BA的int getValue()函数即使加了virtual ,也不能成为多态,一是基类A没有相应的虚函数,二是int 和string的返回类型不一致.因此,在实现输出的话,需要在A类中写一个纯虚函数,然后在各自的子类上覆写该虚函数,写上分别的实现即可.

因此,可以写成下面的样子:

#include <iostream> #include <vector>
#include <string>
using namespace std;

class A
{
public:
void pout() { doout(); }

virtual void doout()=0;
};

class BA: public A
{
public:
void doout() { cout<<m_i<<" "; }
int m_i;
};

class CA: public A
{
public:
void doout() { cout<<m_str<<" "; }
string m_str;
};

class DA : public A
{
public:
void doout() {
for (vector<A *>::iterator it=m_vec.begin();it!=m_vec.end();++it)
(*it)->doout();
}
vector <A *> m_vec;
};

int main()
{
BA *pBa = new BA;
pBa->m_i = 100;

CA *pCa = new CA;
pCa->m_str = "myprogram";

DA da;
da.m_vec.push_back(pBa);
da.m_vec.push_back(pCa);

da.doout();

return 0;
}

下面的网友邦的建议:

不要用这样的语句
cout < < ((A *)(it))->getValue() < < endl;

由于返回类型不一致,很难在基类里声明。把输出功能,放到派生类里去,用一个基类虚函数调用。这样就可以*it.foo()来实现输出了。

是把输出放到派生类的虚函数定义中,在基类用一个非虚函数调用虚函数来实现输出。

以下是重载和覆写的区别?(网上搜到的,转)

重载和覆写有什么区别?

重载有对于已有的方法或操作符进行重构,方法被重载后可以通过其重载的形式或方法原形来调用,有几个重载就有几个调用的形式;操作符重载后会变成你重构的定义.
而覆写则是将之前的方法进行隐藏

重载提供了对一个方法签名的不同参数调用的实现。
覆写提供了子类中改变父类方法行为的实现。

其实很本质的区别就是看函数特征:覆写(Override)的两个函数的函数特征相同,重载(Overload)的两个函数的函数名虽然相同,但函数特征不同。
函数特征包括函数名,参数的类型和个数。
Override 是在继承的时候,如果你写的函数与要继承的函数函数特征相同,那么,加上这个关键字,在使用这个子类的这个函数的时候就看不见父类(或超类)的函数了,它被覆盖掉了。
比如:Derived继承了Base,Base里面有void A(int a)
那么如果你Derived里面觉得A写得不好或不适合这个类,你想重新再写一遍A里的代码,那么就写override void A(int a)这样,原来的那个函数就被你新写的这个覆盖掉了。
Overload 是重载,就是说函数名相同,函数特征不同,系统会根据你提供的参数来调相应的函数。
比如:void A(int a)和void A(int a,int b)
如果你用的是A(1)那么调的是第一个,如果是A(1,1)那么调的是第二个。

都说的好,重载和覆盖还有个关键区别就是:
重载的既可以是父类的方法也可以是子类的方法(虽然名字相同但是参数不同)
而覆盖就是在子类中定义一个和父类一样的方法(关键是名字和参数都是一样的),用中文覆盖来说明这种现象是在好不过了。。。。。。。

重载与覆盖
成员函数被重载的特征:
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual关键字可有可无。
覆盖是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual关键字
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: