2017-02-14 67 views
3

我有以下的底座和繼承的類:爲什麼指針的這個引用是右值?

// Abstract base class Manager. 
class Manager 
{ 
public: 
    Manager(Task*& _task); 
protected: 
    // Reference of a pointer to the current task. 
    Task*& task; 
}; 

// Abstract base class Task. 
class Task 
{ 
    virtual task_rcodes_t run() = 0; 
protected: 
    uint8_t task_id; 
}; 

// Still abstract class Special_Task. 
class Special_Task : public Task 
{ 
public: 
    Special_Task(); 
}; 

// Class Special_Manager. 
class Special_Manager : public Manager 
{ 
public: 
    Special_Manager(); 
protected: 
    // Pointer to the current special task. 
    Special_Task* task; 
}; 

的想法是讓任務指針,以檢測沒有當前任務運行是0。爲了對Task和Spe​​cial_Task指針有共同的訪問權限,它們通過引用傳遞給指針。

爲什麼我收到錯誤信息: 「的類型的非const引用無效初始化‘任務 &’從類型‘Special_Task *’的右值」 結合: 「符號「經理「無法解析」

爲Special_Manager的構造:

// Constructor Manager 
Manager::Manager(Task*& _task) : task (_task) 
{} 

// Constructor Special_Manager 
Special_Manager::Special_Manager() : Manager(task), task (0) 
{} 

由於Special_Task *任務是正常的(指針)VARI能夠,我不明白爲什麼它被認爲是一個右值?

謝謝!

+0

因爲它不是左值,因爲你不能分配給引用。 – EJP

+0

什麼是'Special_Manager();'類'Manager_Special'內部? –

+0

這就是構造函數。我更正了班級名稱中的打字錯誤。 – nubert

回答

3

由於Special_Task *任務是一個正常(指針)變量,我不明白爲什麼它被認爲是一個右值?

任何左值可以通過隱式轉換轉換爲右值。 task是一個左值,因爲它是「範圍內變量的名稱」(請參閱​​cppreference on value categories),並且在您的示例中將其轉換爲右值。

但是在這種情況下,整個左值/右值主要是紅鯡魚。問題是,你正試圖將一種類型的指針分配給不同類型的指針引用,錯誤消息說:

類型的非const引用無效初始化「任務* &」從右值類型的「特殊和下劃線;任務*」。

(順便說一句,我很想知道到底是什麼編譯器/代碼給你的消息,我已經試過所有的gcc版本給代替:從'Task *'類型的右值創建對'Task * &'類型的非常量引用的無效初始化)。

儘管Special_Task是派生類型Task,但不能這樣做。它們各自的指針類型不是子類型; Special_Task *不是Task *,因此Task *&-變量不能被指定爲Special_Task *。 (可能由於Special_Task *可隱式轉換爲Task *這一事實而導致一些混淆,但是,需要注意的是,在這種情況下,生成的指針是右值,而不是左值,這解釋了後者的錯誤消息)。

爲了說明爲什麼你不能指定一個Special_Task *Task *&變量,請看下面的例子:

// Other_Task is a second derived class of Task: 
class Other_Task : public Task { /* ... */ } 

Special_Task st; 
Special_Task *p = &st; // ok, p points to st 

Task *& tp = p; // if it were allowed: tp references p 

Other_Task ot; 
tp = &ot;  // now, p points to ot - which is the wrong type 

上述例子表明,爲什麼不能一個Special_Task *Task *&變量直接分配。因此,在您的代碼中,Special_Task *隱式轉換爲Task *併成爲右值,該值也不能分配給非常量引用。該示例還說明了爲什麼const引用會正常:它會阻止導致p指向錯誤類型的對象的分配。

回到你的問題:多觀察,因爲沒有必要在Managertask做個參考,簡單的解決方法是它的聲明更改爲簡單的指針:

Task* task; 

並改變構造:

Manager(Task* _task); 

的替代解決方案,但沒有一個我建議,將類型更改爲const參考:

Task * const & task; 

Manager(Task* const & _task); 

哦,還有一兩件事:

Special_Manager::Special_Manager() : Manager(task), task (0) 

這傳遞的taskManager構造未初始化的值,然後初始化task 0.1相反,你應該寫:

Special_Manager::Special_Manager() : Manager(0), task (0) 
+0

_「如錯誤消息所示」_不,如果您查看問題的Markdown,您會看到這是一個格式錯誤。 OP沒有逃避'*'。 –

+0

@LightnessRacesinOrbit謝謝,修正。在另一個錯誤消息中還有另一個缺失的*(以某種方式),我也修復了這個問題。書面內容適用於實際的錯誤信息(即回答站)。 – davmac

+0

更改爲const將不允許我在執行期間分配任務= 0,對嗎?另外,我可以像你說的那樣在Manager類中使用普通的Task指針,在Special_Manager中避免額外的Special_Task指針,並且如果需要來自Special_Task的功能,只需在Task指針上使用reinterpretcast! – nubert

1

的錯誤是在這裏:

Special_Manager::Special_Manager() : Manager(task), task (0) 
{} 

0被認爲是rvalue或者是鑄造爲Task*&&類型的int&&。這是可能的,因爲0被認爲是可用於指針轉換值的有效形式。但是因爲構造函數僅使用Task*&,所以它不能採用值爲0的鑄造形式,因此編譯器會拒絕該代碼。

如果你做的類型const Task*&的構造函數的參數,代碼再編譯,因爲const Task*&是與Task*&&類型兼容。

+2

該錯誤與'0'無關。從代碼中刪除'task(0)',你仍然會得到相同的編譯器錯誤。 – davmac

+0

另外:_如果你想讓類型爲const的構造函數參數Task *&_ - 是錯誤的。 'Task * const&'將是合適的類型。引用本身必須是'const'。 – davmac

1

要擴大davmac的答案:

  • 如果YX子類,則:

    • 一個參考-TO-X真的可以指Y。同樣地,
    • a 指針可以指向X可以指向Y

    然而,類型指針-TO-X指針-TO-Y以同樣的方式XY相關本身並不相關,因此

    • 一個指針 - 指向X不能指向指針指向Y(雖然指向最終的指向X所能指向一個Y),和
    • 一個參考到指針-TO- X不能指指針TO- Y任一。

比較模板實例,其中儘管XY的關係std::vector<X>std::vector<Y>是不是在所有相關的。


具體地說,參考到指針-TO- Task不能指指針-TO-Special_Task

相關問題