2011-02-07 99 views
2

在本地C++中,將對象作爲常量引用返回是很有意義的。考慮A類提供只讀訪問B類的一個實例:在C++/CLI中實現常量引用的最佳實踐

class B { 
public: 
    int X; 

    B(int x) 
    : X(x) 
    {} 

    B(const B &b) // copy constructor 
    : X(b.X) 
    {} 

}; 

class A { 
private: 
    B &b; 

public: 
    A(int x) 
    : b(*new B(x)) 
    {} 

    const B &GetB() 
    { 
    return b; 
    } 
}; 

現在客戶有選擇讀A的B-數據要麼非常有效地被引用,或創建它,如果需要自己的副本:

A a1(1); 
const B &b1 = a1.GetB(); // constant reference 
// b1.X = 2; // compilation error 

B b2 = a1.GetB(); // through copy constructor 
b2.X = 2; // ok, but doesn't affect a1 

無論哪種情況,都可以保證外部沒有人能夠更改A的B成員實例中的數據。因此,這是一個完美的解決方案。

的等效CLI結構是這樣的第一眼:

public ref class B { 
public: 
    int X; 

    B(int x) 
    : X(x) 
    {} 

}; 

public ref class A { 
private: 
    B ^b; 

public: 
    A(int x) 
    : b(gcnew B(x)) 
    {} 

    const B %GetB() 
    { 
    return *b; 
    } 
}; 

但這並不多大的意義,因爲它工作在C++/CLI只。當你從一種不同的.NET語言引用它時,例如C#或VB.NET,你根本看不到GetB實現。好了,試試這個代替:

const B ^GetB() 
    { 
    return b; 
    } 

託管指針是恆定的相同的組件內按預期:

A ^a1 = gcnew A(1); 

const B ^b = a1->GetB(); // ok 
b->X = 2; // error C3892: you cannot assign to a variable that is const 

// error C2440: 'initializing' : cannot convert from 'const B ^' to 'B ^' 
B ^b = a1->GetB(); 

在其他.NET組件的同時(使用C++/CLI即使),常數會丟失。事實上,第二assemply內的下列作品引用包含類A中的一個:

A ^a1 = gcnew A(1); 
B ^b2 = a1->GetB(); 
b2->X = 2; // b->X changed within a1 

出人意料的是,這樣你有「更多」從組件比從內外部訪問的對象,因爲語言結構不同的行爲。這是一種預期的行爲嗎?

無論如何,將常量返回對象的想法轉化爲.NET世界的最佳實踐是什麼?你如何實現CLR風格的類A,假如B類支持大量的數據(太多拷貝),而這些數據不應該從A類以外的地方改變?

回答

1

如果你想在.NET中感覺像const,那麼你必須使用不可能改變對象並傳遞這些接口的接口來創建接口。它不如常數那麼方便,但外部效應是相同的。

順便說一句......你的例子很奇怪。第一B具有無意義拷貝構造(因爲其行爲類似編譯器生成的一個),所以也許應該是:

class B 
{ 
public: 
    int X; 

    B(int x) 
     : X(x) 
    {} 
}; 

第一A被泄露它的B會員和吸氣劑不是const的,所以也許應該是:

class A 
{ 
private: 
    B b;  
public: 
    A(int x) 
     : b(x) 
    {} 

    const B& GetB() const 
    { 
     return b; 
    } 
private: 
    // block copy and assignment here 
    // if that was point of reference member 
}; 
4

.NET不幸的是沒有const正確性的概念。 C++/CLI編譯器在本機類型上處理const就好了,但卻使其不適用於託管類型。

對不起,這個壞消息。我和你一樣討厭這個。