2013-07-29 83 views
1

在學習測試時遇到此問題會導致短暫的補充。
如果我有一個class Object和另一個問題:class Point : public Object
現在,如果我得到Object& O1Object& O2,但Object可以Point太...
所以我的主要問題是我怎麼能檢查是否兩個都是Point因爲我需要訪問一個字段Object可是沒有C++如何檢查兩個類是否來自同一個對象

這裏有兩類:

類對象{
市民:
一些功能
};

班級要點:公共對象{
double x;
double y;
public:
相同功能不同實施
};

我想訪問x,y但我需要確保它的第一個Point

預先感謝

+0

「對象」永遠不可能是「點」。 '對象&'可以是'點'(並且與(智能)指針相同)。 –

+0

有沒有辦法確保我在一個點上而不是在一個對象上工作? 我編輯了一個問題,我得到了Object&O1 ... –

+0

'dynamic_cast (ptr)'你在找什麼... – Naszta

回答

7

可以使用的dynamic_cast

Object &o = ...; 
if(Point *p = dynamic_cast<Point*>(&o)) { 
    // ... 
} 

如果動態類型的oPoint或從它導出的if中的代碼將與p是容易獲得的(被執行o的靜態類型是Object)。

如果你已經知道這是一個Point,您可以使用引用

Point &p = dynamic_cast<Point&>(o); 
// ... 

對於這項工作,必須至少在一個Object功能virtual(如果只有析構函數)。

+0

謝謝,也會typeid工作? –

+1

@NadavPed不一定,如果你碰巧從'Point'再次派生。但是,那更確切地取決於你想要做什麼。通常只要對象「* is-a *'Point'」就足夠了,而且通常不需要「* is-a *'Point」而不是* * SuperGoodPoint'「 –

+0

我明白了,所以你說如果我知道方程的一部分是一個Point,那麼typeid就可以工作,但檢查這一點的更一般和正確的方法是使用動態轉換? –

0

它可能是草率的,但如果你有一個指針或對象的引用,你總是可以調用dynamic_cast。如果指針返回爲nullptr,那麼你知道你的對象不是所需對象的派生類。

class CBase { 
     virtual void dummy(){} 
}; 
class CDerived: public CBase { 
    int a; 
}; 

int main() { 
    try { 
    CBase * pba = new CDerived; 
    CBase * pbb = new CBase; 
    CDerived * pd; 

    pd = dynamic_cast<CDerived*>(pba); 
    if (pd==0) cout << "Null pointer on first type-cast" << endl; 

    pd = dynamic_cast<CDerived*>(pbb); 
    if (pd==0) cout << "Null pointer on second type-cast" << endl; 

    } catch (exception& e) {cout << "Exception: " << e.what();} 
    return 0; 
} 
+0

我認爲你的意思是「如果指針返回爲** 0 **」,因爲dynamic_cast失敗時返回0。 –

+0

你能解釋一下,當試圖將一個對象轉換爲一個點時,動態轉換會失敗嗎? –

+0

而且還解釋說這可能是一個糟糕的設計 - 是的,有些情況下,您確實需要這樣做 - 但是到目前爲止,在我開始專業使用C++以來的10年中,我只看到過這樣做的代碼(我能想到的3-4個)。 –

3

一般來說,如果你「需要」知道這一點,那麼你做錯了。有一些例外,但通常情況下,您不需要知道您使用的是哪種類型的對象。您的函數應該被聲明爲virtual,因此如果對象是Point類型的對象,那麼使用Object做某事的代碼可以調用Point中的相關函數。

如果您要訪問xy,你應該做的是間接通過執行需要在xy做任何動作的虛函數。如果你只需要觸摸xy,但你只有(參考或指向)Object,那麼你只是處於錯誤的級別。

+0

是的,當然,正如上面寫的,我正在準備測試,它是關於材料的一些「幹」問題的一部分,我們需要知道一些代碼的行爲。 –

1

您可以依賴C++標準庫提供的類型信息。以下示例已從cppreference.com提取:

#include <iostream> 
#include <typeinfo> 
#include <string> 
#include <utility> 

class person 
{ 
    public: 

    person(std::string&& n) : _name(n) {} 
    virtual const std::string& name() const{ return _name; } 

    private: 

    std::string _name; 
}; 

class employee : public person 
{ 
    public: 

    employee(std::string&& n, std::string&& p) : 
     person(std::move(n)), _profession(std::move(p)) {} 

    const std::string& profession() const { return _profession; } 

    private: 

    std::string _profession; 
}; 

void somefunc(const person& p) 
{ 
    if(typeid(employee) == typeid(p)) 
    { 
     std::cout << p.name() << " is an employee "; 
     auto& emp = dynamic_cast<const employee&>(p); 
     std::cout << "who works in " << emp.profession() << '\n'; 
    } 
} 

int main() 
{ 
    employee paul("Paul","Economics"); 
    somefunc(paul); 
} 
+0

呃,但是你可以有'班長:公職人員' - 是'員工'的經理嗎?不是,但是'manager'具有'employee'的所有屬性,但也有一些額外的(例如,他管理的是什麼/誰),這不屬於'員工'。 –

+0

如果經理不是員工,那麼它不應該從員工繼承(繼承意味着模擬「是 - 一個」關係)。 – Escualo

+0

是的,我的觀點是,「經理人」是一個「僱員」,但「typeid(僱員)」不等於'經理人',所以這種方法不會在這種情況下可靠地工作。 –

相關問題