1. 程式人生 > 程式設計 >詳解C++之函式過載

詳解C++之函式過載

函式過載本質

c++中通過函式名和函式確定一個函式
所以相同的函式名,不同引數也是可以的
不同於c語言,c語言沒有函式過載,函式的本質地址就是函式名
函式過載發生在同一個作用域內

類中的過載

建構函式過載
普通成員函式過載
靜態成員函式過載

全域性函式、靜態成員函式、普通成員函式可以發生過載嗎?

本質就是函式名和函式引數不同,並且發生在同一個作用域
靜態函式和普通成員函式是可以的
全域性函式作用域在全域性作用域,所以不可以

問題1:當父類的成員函式和子類的成員函式相等,會發生過載嗎?

本質還是上面說的,因為父類和子類的作用域不在同一個

看一段程式碼

 #include <iostream>

class father{
public:
 father() {
  std::cout << "father()" << std::endl;
 }
 void print() {
  std::cout << "father print" << std::endl;
 }
};

class child : public father{
public:
 child() {
  std::cout << "child()" << std::endl;
 }
 void print(int a) {
  std::cout << "child print = " << a << std::endl;
 }
};

int main(){
 father* father_test = new father();
 father_test->print(); //列印father print

 child* child_test2 = new child();
 child_test2->print(); //編譯錯誤no matching function for call to 'child::print()'
      
 return 0;
}

由列印輸出可得第一個列印屬於father正常輸出,沒問題,第二個列印是編譯錯誤,我們其實想訪問的是父類的print,但是由於子類定義了print,那麼在子類的作用域中,print這個函式現在只存在一個,那就是void print(int a),如果想呼叫父類的就要顯示指定child_test2->father::print();

問題2,子類可以重寫父類的函式嗎,或者說定義相同的?

看程式碼

#include <iostream>

class father{
public:
 father() {
  std::cout << "father()" << std::endl;
 }
 void print() {
  std::cout << "father print" << std::endl;
 }
};

class child : public father{
public:
 child() {
  std::cout << "child()" << std::endl;
 }
 void print() {
  std::cout << "child print" << std::endl;
 }
};

int main(){
 father* father_test = new father();
 father_test->print(); //列印father print

 child* child_test2 = new child();
 child_test2->print(); //child print

 return 0;
}

可見是可以定義相同的函式,並重寫的

問題3,當全域性運算子過載遇上類中的運算子過載,優先順序是什麼

 #include <iostream>
class child;
class father{
public:
 father() {
  std::cout << "father()" << std::endl;
 }
 bool operator==(const father& e) {
  std::cout << "void print(const father& e)" << std::endl;
 }
};
bool operator==(const father& e1,const father& e2) {
 std::cout << "void print(const child& e1,const child& e2)" << std::endl;
}

class child : public father{
public:
 child() {
  std::cout << "child()" << std::endl;
 }
};


int main(){
 child child1_test;
 child child2_test;

 child1_test==child2_test;
 return 0;
}

輸出為void print(const father& e)類中的運算子過載優先順序大於全域性

當複製相容遇上全域性過載呢?

#include <iostream>
class child;
class father{
public:
 father() {
  std::cout << "father()" << std::endl;
 }
 bool operator==(const father& e) {
  std::cout << "void print(const father& e)" << std::endl;
 }
};
bool operator==(const child& e1,const child& e2) {
 std::cout << "void print(const child& e1,const child& e2)" << std::endl;
}

class child : public father{
public:
 child() {
  std::cout << "child()" << std::endl;
 }
};


int main(){
 child child1_test;
 child child2_test;

 child1_test==child2_test;
 return 0;
}

列印:"void print(const child& e1,const child& e2)"

僅僅變化了,全域性的函式引數型別,正常來說類中和全域性的==都是可以的,但是當類中的需要一個預設的轉換,子類到父類,全域性的是直接型別就對的上的,編譯器就優先使用全域性的

說到運算子過載,我們現在定義函式實現類的功能有三種選擇:成員函式,全域性函式,全域性函式+友元函式

1.看是否需要虛擬函式,如果需要虛擬函式,那麼肯定是類的成員函式

2.看是否定義的是<<或者>>運算子,我們都知道列印輸出是全域性<<,但是為什麼呢,看一下實際的原型針對String而言ostream& operator<<(ostream& output,const String& string)我們使用的時候就是 std::cout << "haha";
如果定義為類中的就是ostream& operator<<(ostream& output)使用起來就是 "haha"<<"std::cout"看出差別了吧,如果定義在類中使用起來就很彆扭,繼續上面的結果,如果是<<或者>>運算子,然後如果需要訪問private域,那麼就把全域性函式變為類對應的友元函式

3.當需要對左邊的引數進行型別轉換,需要定義全域性函式,因為類中操作符函式,左邊的就是類本身,如果需要訪問private域,那麼就把全域性函式變為類對應的友元函式

4.其他情況為類的成員函式

以上就是詳解C++之函式過載的詳細內容,更多關於c++之函式過載的資料請關注我們其它相關文章!