C++ 靜態(tài)成員函數(shù)能不能被繼承?你知道嗎?
在C++中,靜態(tài)成員函數(shù)可以被繼承?!?/span>
寫(xiě)個(gè)簡(jiǎn)單的代碼驗(yàn)證:
圖片
靜態(tài)成員函數(shù)對(duì)比普通函數(shù)有點(diǎn)特殊,靜態(tài)成員函數(shù)是屬于類本身的,而不是類的對(duì)象。可以通過(guò)類名直接調(diào)用靜態(tài)成員函數(shù),而無(wú)需創(chuàng)建類的實(shí)例(對(duì)象)。靜態(tài)成員函數(shù)通常用來(lái)操作類的靜態(tài)成員變量,靜態(tài)成員變量也是屬于類本身的,不需要通過(guò)對(duì)象來(lái)訪問(wèn)?!?/span>
比如:
class MyClass {
public:
static int counter; // 靜態(tài)成員變量
static void increment() { // 靜態(tài)成員函數(shù)
counter++;
}
};
靜態(tài)成員函數(shù)可以是Virtual嗎?
不行!因?yàn)閮烧咴O(shè)計(jì)機(jī)制就是相悖的
虛函數(shù)的核心特性是在運(yùn)行時(shí)動(dòng)態(tài)決定調(diào)用哪個(gè)版本的函數(shù)(即動(dòng)態(tài)綁定)。這是通過(guò)虛函數(shù)表(vtable)來(lái)實(shí)現(xiàn)的。虛函數(shù)表保存著類的虛函數(shù)地址,程序運(yùn)行時(shí),基類或派生類的指針或引用會(huì)根據(jù)對(duì)象的實(shí)際類型(而不是聲明的類型)來(lái)調(diào)用對(duì)應(yīng)的虛函數(shù)版本。這就是所謂的多態(tài)。
為了實(shí)現(xiàn)這一點(diǎn),虛函數(shù)需要依賴實(shí)例,即每個(gè)對(duì)象都有一個(gè)與其類型相關(guān)的虛函數(shù)表。在調(diào)用虛函數(shù)時(shí),程序通過(guò)對(duì)象的虛函數(shù)表來(lái)決定調(diào)用哪個(gè)函數(shù)版本?!?/span>
靜態(tài)成員函數(shù)是與類本身綁定的,而不是與類的實(shí)例綁定。靜態(tài)成員函數(shù)沒(méi)有 this 指針,也就無(wú)法訪問(wèn)對(duì)象的實(shí)例成員?!?/span>
靜態(tài)成員函數(shù)的調(diào)用通過(guò)類名直接訪問(wèn),而不是通過(guò)對(duì)象指針或引用。這意味著靜態(tài)成員函數(shù)的調(diào)用和虛函數(shù)機(jī)制的工作方式是完全不同的。
所以靜態(tài)成員函數(shù)不參與多態(tài):靜態(tài)成員函數(shù)的調(diào)用是通過(guò)類本身而不是通過(guò)對(duì)象進(jìn)行的,因此不涉及動(dòng)態(tài)綁定。虛函數(shù)的目的是支持多態(tài),而靜態(tài)成員函數(shù)的設(shè)計(jì)則與這種機(jī)制不兼容?!?/span>
靜態(tài)成員函數(shù)可以重寫(xiě)嗎?
不行!
靜態(tài)成員函數(shù)是可以被繼承的,派生類會(huì)繼承這個(gè)靜態(tài)成員函數(shù),但不能對(duì)其進(jìn)行重寫(xiě)。因?yàn)殪o態(tài)成員函數(shù)和類的實(shí)例無(wú)關(guān),它們是與類本身綁定的,而不是和對(duì)象的狀態(tài)綁定。
如果在派生類中定義一個(gè)與基類同名的靜態(tài)成員函數(shù),那么這只是一個(gè)隱藏了基類的靜態(tài)函數(shù),而不是重寫(xiě)。換句話說(shuō),它并不會(huì)改變基類靜態(tài)成員函數(shù)的行為。
class Base {
public:
static void showMessage() {
std::cout << "Base class message" << std::endl;
}
};
class Derived : public Base {
public:
static void showMessage() {
std::cout << "Derived class message" << std::endl;
}
};
int main() {
Base::showMessage(); // 輸出:Base class message
Derived::showMessage(); // 輸出:Derived class message
Base* b = new Derived();
b->showMessage(); // 輸出:Base class message,因?yàn)殪o態(tài)函數(shù)與對(duì)象無(wú)關(guān)
return 0;
}
輸出結(jié)果驗(yàn)證
b->showMessage();輸出還是Base的而不是子類的。
總結(jié)
靜態(tài)成員函數(shù)可以被繼承:派生類可以繼承基類的靜態(tài)成員函數(shù),但靜態(tài)函數(shù)本身與對(duì)象無(wú)關(guān),不能在派生類中重寫(xiě)?!?/span>
不能進(jìn)行重寫(xiě):靜態(tài)成員函數(shù)不支持重寫(xiě),因?yàn)樗鼈兪菍儆陬惐旧?,而不是?duì)象實(shí)例?!?/span>
通過(guò)類名調(diào)用:靜態(tài)成員函數(shù)需要通過(guò)類名來(lái)調(diào)用,可以通過(guò)基類或派生類來(lái)調(diào)用。