在本地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類以外的地方改變?