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

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

2013-09-28 17:02 316 查看
虚函数就是实现函数的覆写,

它们以下特点:

(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关键字

举例说明:

覆写(overriding):

class A {

System.out.println("This is class A");

}

class B extends A {

System.out.println("This is class B");

}

重载(overloading):

class C {

void print(int i) {

System.out.println(i);

}

void print(float f) {

System.out.println(f);

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: