溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C++ Virtual關鍵字的使用方法

發(fā)布時間:2020-11-02 15:13:02 來源:億速云 閱讀:168 作者:Leah 欄目:開發(fā)技術

C++ Virtual關鍵字的使用方法?相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。

基礎理解和demo

普通的繼承

#include<iostream>

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

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

int main() {
  Child c;
  c.print();
  return 0;
}

輸出結果為 "Child"

但是如果是 "父類的指針指向子類的對象" 這種情況下, 使用這個父類的指針去調用被重寫的方法呢, 結果會是什么呢&#63; 從語法的本質上講, 子類對象的內存前半部分就是父類, 因為可以將子類對象的指針直接轉化為父類。

#include<iostream>

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

// 注意這里必須是 public Parent
// 不然會報錯 cannot cast 'Child' to its private base class 'Parent'
class Child : public Parent {
public:
  void print() {
    std::cout << "Child" << std::endl;
  }
};

int main() {
  Parent* p = new Child();
  p->print();
  return 0;
}

這個時候輸出的是 "Parent"  。

所以, 當一個成員函數(shù)需要被子類重寫, 那么必須將其聲明為virtual, 也就是 虛函數(shù) , 注意, 子類覆寫的方法的virtual關鍵字會自動繼承而來, 可以顯示地寫或者不寫(建議還是寫上)。

這樣修改完就沒問題了:

#include<iostream>

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

class Child : public Parent {
public:
  virtual void print() {
    std::cout << "Child" << std::endl;
  }
};

int main() {
  Parent* p = new Child();
  p->print();
  return 0;
}

加深理解

Virtual 關鍵字的一個重要概念 "只有在通過基類指針或引用間接指向派生類子類型時多態(tài)性才會起作用" , 也就是說, 基類的函數(shù)調用如果有virtual則根據(jù)多態(tài)性調用派生類的,如果沒有virtual則是正常的靜態(tài)函數(shù)調用,還是調用基類的。

舉個例子

#include <iostream.h>
class Base
{
public:
virtual void f(float x){ cout << "Base::f(float) " << x << endl; }
void g(float x){ cout << "Base::g(float) " << x << endl; }
void h(float x){ cout << "Base::h(float) " << x << endl; }
};
 
class Derived : public Base
{
public:
virtual void f(float x){ cout << "Derived::f(float) " << x << endl; }
void g(int x){ cout << "Derived::g(int) " << x << endl; }
void h(float x){ cout << "Derived::h(float) " << x << endl; }
};
 
void main(void)
{
Derived d;
Base *pb = &d;
Derived *pd = &d;
// Good : behavior depends solely on type of the object
pb->f(3.14f); // Derived::f(float) 3.14
pd->f(3.14f); // Derived::f(float) 3.14
// Bad : behavior depends on type of the pointer
pb->g(3.14f); // Base::g(float) 3.14
pd->g(3.14f); // Derived::g(int) 3 (surprise!)
// Bad : behavior depends on type of the pointer
pb->h(3.14f); // Base::h(float) 3.14 (surprise!)
pd->h(3.14f); // Derived::h(float) 3.14
}

粘貼這個博客的一段話, 表達的就是這個意思:

bp 和dp 指向同一地址,按理說運行結果應該是相同的,而事實上運行結果不同,所以他把原因歸結為C++的隱藏規(guī)則,其實這一觀點是錯的。決定bp和dp調用函數(shù)運行結果的不是他們指向的地址,而是他們的指針類型。 “只有在通過基類指針或引用間接指向派生類子類型時多態(tài)性才會起作用”(C++ Primer 3rd Edition)。pb是基類指針,pd是派生類指針,pd的所有函數(shù)調用都只是調用自己的函數(shù),和多態(tài)性無關,所以pd的所有函數(shù)調用的結果都輸出Derived::是完全正常的;pb的函數(shù)調用如果有virtual則根據(jù)多態(tài)性調用派生類的,如果沒有virtual則是正常的靜態(tài)函數(shù)調用,還是調用基類的,所以有virtual的f函數(shù)調用輸出Derived::,其它兩個沒有virtual則還是輸出Base::很正常啊 ,nothing surprise! 所以并沒有所謂的隱藏規(guī)則

看完上述內容,你們掌握C++ Virtual關鍵字的使用方法的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI