溫馨提示×

溫馨提示×

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

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

abstract中如何使用class 抽象類

發(fā)布時間:2021-07-30 17:44:12 來源:億速云 閱讀:329 作者:Leah 欄目:大數(shù)據(jù)

abstract中如何使用class 抽象類,相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。

1. 抽象類的定義

首先來說虛函數(shù);

虛函數(shù)是在基類中被聲明為virtual,并在派生類中重新定義的成員函數(shù),可實現(xiàn)函數(shù)的動態(tài)重載;

動態(tài)重載也就是在可以依據(jù)后期的傳入類的類型,選擇具體的實現(xiàn)函數(shù);

純虛函數(shù)的聲明有著特殊的語法格式:virtual 返回值類型成員函數(shù)名(參數(shù)表)=0;

包含有虛函數(shù)是成為抽象類的充要條件;

包含了虛函數(shù)的類被稱為抽象類,抽象類中可以有純虛函數(shù),也可以有其他非虛函數(shù);因為抽象類中都是沒有定義的虛函數(shù),因此不能定義對象;

在C++中,我們可以把只能用于被繼承而不能直接創(chuàng)建對象的類設(shè)置為抽象類(Abstract Class)。

舉一個小栗子~~

比如我今天想寫一個代碼,可以自動幫我炒肉菜,我需要實現(xiàn)的效果是,如果傳入雞肉,則做宮保雞??;如果傳入排骨,則做土豆燉排骨;如果傳入牛肉,則做成黑椒牛仔骨;每次 只做一道菜;

因為無法預(yù)料到具體使用時可能會傳入的肉的類型,總不能三個對象都創(chuàng)建?這個時候可以創(chuàng)建抽象類 肉類;以及派生類 雞肉,排骨,和牛肉;

這三個類中都需要有對應(yīng)做菜的函數(shù),如cook();

#include<iostream>
using namespace std;
class Meat   //抽象類:肉類
{
public:
    virtual void cook()=0;//純虛函數(shù)
};

class Chicken:public Meat //派生類:雞肉
{
public:
    void cook(){
        cout<<"熱鍋下油,加入黃瓜丁和胡蘿卜丁翻炒至半熟,劃入雞丁翻炒,最后放入買好的宮保雞丁醬和花生米即可"<endl;
    }
};

class Rib:public Meat{ //派生類:排骨
public:
    void cook(){
        cout<<"熱鍋下油,排骨炒至半熟,放入土豆塊翻炒,加水收汁即可"<<endl;
    }
};

class Beef:public Meat{ //派生類:牛肉
public:
    void cook(){
        cout<<"熱鍋下油,洋蔥炒香,加入牛仔骨和黑椒醬,加水收汁即可"<<endl;
    }
};

int main()
{
    Meat *realmeat; //定義對象指針數(shù)組
    std::string mymeat = "Chicken";
    if(mymeat == ""){
      realmeat = new Chicken();
    }else if(mymeat == "Rib"){
      realmeat = new Rib();;
    } else if (mymeat == "Beef"){
      realmeat = new Beef();
    }
    realmeet->cook();
    return 0;

}

大概的一個例子,不知道有沒有解釋清楚,有問題歡迎指正,在上面的例子中也能看到,抽象類是不能創(chuàng)建對象的,但是可以定義指針指向抽象類;

抽象類的規(guī)定

(1)抽象類只能用作其他類的基類,不能建立抽象類對象。

(2)抽象類不能用作參數(shù)類型、函數(shù)返回類型或顯式轉(zhuǎn)換的類型。

(3)可以定義指向抽象類的指針和引用,此指針可以指向它的派生類,進而實現(xiàn)多態(tài)性。

2. 在ORBSLAM3中的使用

在ORBSLAM3中的使用,也說明了抽象類存在的意義,也就是實現(xiàn)了多態(tài);可以把它理解成一個操作接口,具體的實現(xiàn)在派生類中;

ORBSLAM3中因為新加入了KB模型,這就導(dǎo)致無法在最一開始后時候確定相機的類型,是普通針孔相機(Pinhole) 還是魚眼相機(使用KB);

如果不使用抽象類的話,以單目相機為例,除了需要為Pinhole和KB各自創(chuàng)建一個類,同時在需要使用相機參數(shù)的時候,定義兩個對象,一個Pinhole,一個KB;

然后,在使用時,只使用其中的一個;

有了抽象類,就可以先將相機的模型聲明成一個抽象的類型:GeometricCamera* mpCamera;然后按照配置文件中的輸入是Pinhole還是KannalaBrandt8, 定義對象mpCamera即可;如:

mpCamera = new Pinhole(vCamCalib); //或者
mpCamera = new KannalaBrandt8(vCamCalib);

同時,因為模型不同,不同坐標系之間的轉(zhuǎn)換函數(shù)也會不同,以投影函數(shù)為例:

首先在抽象類中定義一個虛函數(shù):

virtual cv::Point2f project(const cv::Point3f &p3D) = 0;

然后具體的實現(xiàn)時, 在KB模型中為

    cv::Point2f KannalaBrandt8::project(const cv::Point3f &p3D) {
        const float x2_plus_y2 = p3D.x * p3D.x + p3D.y * p3D.y;
        const float theta = atan2f(sqrtf(x2_plus_y2), p3D.z);
        const float psi = atan2f(p3D.y, p3D.x);

        const float theta2 = theta * theta;
        const float theta3 = theta * theta2;
        const float theta5 = theta3 * theta2;
        const float theta7 = theta5 * theta2;
        const float theta9 = theta7 * theta2;
        const float r = theta + mvParameters[4] * theta3 + mvParameters[5] * theta5
                        + mvParameters[6] * theta7 + mvParameters[7] * theta9;

        return cv::Point2f(mvParameters[0] * r * cos(psi) + mvParameters[2],
                           mvParameters[1] * r * sin(psi) + mvParameters[3]);

    }

在Pinhole中為:

    cv::Point2f Pinhole::project(const cv::Point3f &p3D) {
        return cv::Point2f(mvParameters[0] * p3D.x / p3D.z + mvParameters[2],
                           mvParameters[1] * p3D.y / p3D.z + mvParameters[3]);
    }

使用時按照傳入相機的類型,mpCamera->project(p3D) 代碼會根據(jù)相機的類型自動調(diào)用對應(yīng)的實現(xiàn)函數(shù);

3. 編譯報錯

  a.  invalid new-expression of abstract class type ‘×××ב

這種情況一般是抽象類中的虛函數(shù),并沒有在派生類中被實現(xiàn),也就是派生類中沒有定義;一般編譯的時候會指示出具體的問題出處,如下面:

src/Tracking.cc: In member function ‘bool ORB_SLAM2::Tracking::ParseCamParamFile(cv::FileStorage&)’:
src/Tracking.cc:169:34: error: invalid new-expression of abstract class type ‘ORB_SLAM2::EUCM’
     mpCamera = new EUCM(vCamCalib);
                                  ^
In file included from src/Tracking.cc:28:0:
/include/CameraModels/EUCM.h:12:7: note:   because the following virtual functions are pure within ‘ORB_SLAM2::EUCM’:
 class EUCM final : public GeometricCamera{
       ^
In file included from include/Tracking.h:30:0,
                 from src/Tracking.cc:21:
include/CameraModels/GeometricCamera.h:38:29: note: 	virtual cv::Point2f ORB_SLAM2::GeometricCamera::Camera2Img(const cv::Mat&)
         virtual cv::Point2f Camera2Img(const cv::Mat& m3D) = 0;

指出了抽象類中的Camera2Img() 在派生類EUCM中沒有對應(yīng)的實現(xiàn),而其實我這里有對應(yīng)的函數(shù),但是形參類型寫錯了;

b. C++ : Cannot declare field to be of abstract type

這里是抽象類的實例化問題,也就是上面說到的,抽象類并不能定義對象,但是可以定義指向抽象類的指針;上面炒菜的例子中,如果我定義:

 Meat realmeat;

就會出現(xiàn)類似的報錯,但是定義

 Meat *realmeat;

看完上述內(nèi)容,你們掌握abstract中如何使用class 抽象類的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問一下細節(jié)

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

AI