2009-04-10 80 views
6

我試圖回答這個問題通過將參考指針,而不是指向提及here的指針這樣的:從派生*轉換爲基地*

class Parent 
{ 
}; 

class Child : public Parent 
{ 
}; 

void RemoveObj(Parent*& pObj) 
{ 
    delete pObj; 
    pObj = NULL; 
} 

int main() 
{ 
    Parent* pPObj = new Parent; 
    Child* pCObj = new Child; 
    pPObj = new Parent(); 
    pCObj = new Child(); 



    RemoveObj(pPObj); 
    RemoveObj(pCObj); // This is line 32 
    return 1; 
} 

但是,這會產生以下編譯器錯誤的線32:

錯誤C2664: 'RemoveObj':不能 轉換參數1從 '少年*' 來 '父* &'

我同意從孩子說轉換**於母公司**是不允許的。但爲什麼這種轉換也是不允許的?

+0

爲什麼返回1;在main()的結尾?它不應該是返回0; ? – DeadHead 2009-04-10 09:06:36

+0

我只是複製粘貼代碼鏈接的問題..但這是不相關的問題 – Naveen 2009-04-10 09:08:32

+0

哦,我知道這是不是真的有關的問題。只是好奇心加上思考,我的知識可能存在一些差距。 – DeadHead 2009-04-10 09:10:09

回答

7

Child*類型的對象無法綁定到Parent*&,原因與Child**無法轉換爲Parent**完全相同。允許程序員(有意或無意)在沒有演員的情況下打破類型安全。

class Animal {}; 

class DangerousShark : public Animal {}; 

class CuteKitten : public Animal {}; 

void f(Animal*& animalPtrRef, Animal* anotherAnimalPtr) 
{ 
    animalPtrRef = anotherAnimalPtr; 
} 

void g() 
{ 
    DangerousShark myPet; 
    CuteKitten* harmlessPetPtr; 

    f(harmlessPetPtr, &myPet); // Fortunately, an illegal function call. 
} 

編輯

我覺得有些混亂的原因是,的鬆散使用單詞「轉換」和「轉換」的。

引用不能反彈,不同於可以重新分配對象,所以在引用的背景下,當我們講的轉換,我們只能是關注初始化一個新的參考。

引用總是綁定到一個對象,並從OP的問題很明顯,他的目標是獲得一個參考是一個直接綁定到一個現有的對象。只有當用於初始化參考的對象與參考類型參考兼容時,才允許使用該參考。實質上,只有類型相同,或者對象的類型是從引用的類型派生而來,並且引用類型至少與初始化對象一樣具有cv限定時纔是如此。特別是,不管指向類型的關係如何,指向不同類型的指針都不是引用兼容的。

在其他情況下,引用可以用可以轉換爲引用類型的東西來初始化。但是,在這些情況下,引用必須是const且不會變化,並且轉換將創建一個臨時對象,引用將被綁定到此臨時對象,而不是原始對象。正如所指出的,這不適合OP的激勵範例的要求。

總之,Child可以直接綁定到Parent&,但Child*不能直接綁定到Parent*&。 A Parent* const&可以使用Child*初始化,但該引用實際上會綁定到從Child*對象初始化的臨時對象Parent*

4
  • 您的課程沒有虛擬功能。請參閱FAQ 20.7

  • 因爲Parent *&是對指向Parent對象的指針的引用。您正在傳遞一個指向Child的指針 - 這些是不兼容的類型。您可以綁定一個臨時的一個const引用也就是說,如果你改變你的參數:

    void RemoveObj(Parent* const& foo);

但你將不能夠做很多與此有關。

這只是一個測試代碼,所以我沒有做任何虛擬析構函數。如果我在RemoveObj()的第二次調用正確理解,我拿到它可以作爲一個const參考函數傳遞一個臨時母公司*對象。它是否正確?

我強烈建議你在標準C++ 98模式下運行下面的程序,一旦在,然後再註釋掉foo(b)和註釋掉delete b後。接下來,嘗試投入virtual~s()之前。差異應該是不言自明的!

#include <iostream> 
using namespace std; 
struct s { 
    s() {cout << __func__ << endl; } 
    ~s() {cout << __func__ << endl; } 
}; 

struct t : s { 
    t() {cout << __func__ << endl; } 
    ~t() {cout << __func__ << endl; } 
}; 

void foo(s* const& x) { delete x; } 

int main() { 
t* b = new t; 
foo(b); 
//delete b; 
} 
0
類型

* &是類型的另一個語法形式**和Parent * &和兒童* &是互不相關以及父**和兒童** - 這些是不同的類型不是在一個類層次結構。

0

這不適用於Dirk提到的原因。如果你真的需要一個RemoveObj方法,那麼我會只是你的新分配的子對象保存爲母公司*:

#include <iostream> 

class Parent 
{ 
public: 
    virtual ~Parent() 
    { 
     std::cout << "Parent destructor" << std::endl; 
    } 
}; 

class Child : public Parent 
{ 
public: 
    virtual ~Child() 
    { 
     std::cout << "Child destructor" << std::endl; 
    } 
}; 

void RemoveObj(Parent*& pObj) 
{ 
    delete pObj; 
    pObj = NULL; 
} 



int main (int argc, const char * argv[]) { 

    Parent* pPObj = new Parent; 
    Parent* pCObj = new Child; 

    RemoveObj(pPObj);  
    RemoveObj(pCObj); // This is line 32 


    return 0; 
} 
1

您可以轉換Child* to a Parent*:這將創建一個臨時的。但是你不能將非const引用綁定到該臨時對象。

這不是**/*&/etc的問題。你試圖做的是完全合適的,並且合理。鯊魚對小貓有同樣的問題:不是混合小貓和鯊魚的問題。您不能將非常量引用綁定到該未命名的指針。

這不是Parent** vs. Child**問題:在那裏,如果Child**Parent**,那麼可以分配p[0] = new NotAChild;。 A的所有子類型的對象的集合不是A的集合。