2011-02-07 98 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就好了,但却使其不适用于托管类型。

对不起,这个坏消息。我和你一样讨厌这个。