C++ (pure)virutal function & abstract class

C++ (pure)virutal function & abstract class

virtual function

假想我們定義了一個Vehicle的類別,當中有一個名為go的成員函數。go的作用是讓Vehicle物件向前移動。Vehicle還有多個子類別,如BoatCarPlane

很顯然地,這三種交通工具向前移動的方式各不相同,在這種情況下,我們可以override(即重定義)父類別Vehicle裡定義(或宣告)過的函數go,在BoatCarPlane中各自實現相應的前進方式。

到了這裡,可能還看不出虛擬函數的作用。現在假想我們有一個Vehicle類別的指標,它可能會動態地指向BoatCarPlane

如果我們不使用虛擬函數,那麼C++就無法在執行時判斷指標指向的物件是屬於哪個子類別的,它只能依據指標的類別(即Vehicle)調用相應的go函數(即Vehicle::go)。

反之,如果我們將Vehicle::go宣告為虛擬函數,C++就能在執行時正確地解析出指標所指向的物件是屬於哪個子類別,進而調用該子類別override的函數(即Boat::goCar::goPlane::go),這個就是所謂的runtime polymorphism,late binding。

TensorRT/samples/common/logging.h中定義了Logger的成員函數log

class Logger : public nvinfer1::ILogger
{
public:
    //...
	void log(Severity severity, const char* msg) override
	{
	    //LogStreamConsumer是std::ostream的子類別
	    LogStreamConsumer(mReportableSeverity, severity) << "[TRT] " << std::string(msg) << std::endl;
	}
    //...
};

這裡使用了一個關鍵字override,根據Is the ‘override’ keyword just a check for a overridden virtual method?,這只是一種保護機制,確保子類別Logger的函數log有正確地override其父類別nvinfer1::ILogger的函數log,而非又重新定義了另外一個函數。

Logger的父類別nvinfer1::ILogger定義於TensorRT/include/NvInferRuntimeCommon.h

namespace nvinfer1
{
class ILogger
{
public:
    //...
	virtual void log(Severity severity, const char* msg) TRTNOEXCEPT = 0;
};
//...
}

上面的代碼中在函數宣告結尾加上了=0,這代表nvinfer1::ILogger::log是一個"純虛擬函數",只做宣告,不包含任何定義。

因為nvinfer1::ILogger包含了至少一個純虛擬函數,所以我們可以說它是抽象類別(abstract class)。

參考連結

Virtual Function in C++

Pure Virtual Functions and Abstract Classes in C++

Is the ‘override’ keyword just a check for a overridden virtual method?

发布了90 篇原创文章 · 获赞 9 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/keineahnung2345/article/details/104075956