C++函式過載、重寫與重定義
阿新 • • 發佈:2019-01-09
- 過載:同一個類中(不一定是在類中),定義了多個同名的函式,這些函式的引數列表(引數個數,引數類型別)不完全相同,這是函式的過載。函式的返回值型別不能作為是否是過載的判斷依據,因為返回值型別可以捨棄、可以自動轉換等。
- 重寫:類的繼承裡,子類裡含有與父類裡同名的虛擬函式,函式名、函式返回值型別和引數列表必須相同,許可權可以不同。如果返回值型別或者引數列表不同,這是子類方法的重定義,即使加了virtual也不會體現出多型。
- 重定義:父類和子類中有相同名稱的非虛擬函式,返回值型別、引數列表可以不同。子類物件呼叫該同名方法時,子類方法將覆蓋父類方法。
程式1:方法的過載
class A
{
public :
A(){}
~A(){}
int getMax(int a,int b){return a>b?a:b;}//1
double getMax(int a,int b){return a>b?a:b;}//2
double getMax(double a,double b){return a>b?a:b;}//3
};
上面的程式中,方法1和方法3是函式的過載(引數列表不同);但是方法2不是,因為與方法1比起來只是返回值不同,而返回值不能作為函式過載的判斷,在編譯階段會出錯。
程式2:方法的重定義
class A
{
public:
A (){}
~A(){}
void show(){cout<<"A::show()"<<endl;}
};
class B:public A
{
public:
B(){}
~B(){}
void show(){cout<<"B::show()"<<endl;}
};
int main()
{
A *a = new A();
B *b = new B();
A *c = new B();
a->show();
b->show();
c->show();
system("pause" );
return 0;
}
上面的程式中,show()是普通的成員函式,子類B重新定義了show(),因此b->show()的結果是“B::show()”。如果B中沒有重新定義show(),那b->show()的結果是“A::show()”。在類的多型中,基類指標c可以指向子類物件,由於show()不是虛擬函式,因此呼叫show時將執行指標本身的型別的show(),即A::show()。
如果我修改B中show()的返回值型別或者引數列表:
class B:public A
{
public:
B(){}
~B(){}
int show(int a){cout<<"B::show()"<<endl; return 1;}
};
那麼下面程式中b->show()將報錯,因為b中show覆蓋了A中的show方法。
程式3:方法的重寫
class A
{
public:
A(){}
~A(){}
virtual void show(){cout<<"A::show()"<<endl;}
virtual void print(){cout<<"A::print()"<<endl;}
virtual void eat(){cout<<"A::eat()"<<endl;}
};
class B:public A
{
public:
B(){}
~B(){}
virtual void show(){cout<<"B::show()"<<endl; }
virtual int print(){cout<<"B::print()"<<endl;}
virtual void eat(int a){cout<<"B::eat()"<<endl;}
};
上面程式定義了基類A和子類B,並且定義了3個虛擬函式show(), print() 和eat()。
- show():是重寫,返回型別、引數列表相同;
- print():不是重寫,返回型別不同;
- eat():是不是重寫??反正基類指標派生類物件時,不會呼叫派生類的eat()方法。
刪掉兩個類裡面的print()方法定義,執行下面程式:
int main()
{
A *c = new B();
c->show();
c->eat();
system("pause");
return 0;
}
可以看到,show函式是虛擬函式,並且在A和B中返回值型別、引數列表相同,是重寫,體現了類的多型。而eat函式雖然也是虛擬函式,但是並沒有呼叫“指向物件的型別”的方法。