我在Mark Allen Weiss的数据结构书中遇到了以下一段代码。
template <class Object>
class Cref
{
public:
Cref ( ) : obj ( NULL ) { }
explicit Cref( const Object & x ) : obj ( &x ) {
const Object & get( ) const
{
if ( isNull( ) )
throw NullPointerException( ) ;
else
return *obj;
}
bool isNull( ) const
( return obj == NULL; }
private:
const Object *obj;
};
所以这里的重点是指定null /初始化常量引用。但我不确定我理解以下内容: 1.我们用另一个常量引用x初始化一个常量引用。但为什么它又作为obj(&amp; x)完成了?和&amp;在const对象&amp; x与obj(&amp; x)中的&amp; x不同?我看到了这一点,但不清楚为什么会如此。请解释一下。 2. get方法() - 我们尝试返回此类的私有成员obj的const引用。它已经是一个const引用。为什么返回* obj而不仅仅是obj? 3.为何显式关键字?如果发生隐式类型转换会发生什么?有人能为此提供一个场景吗?
由于
答案 0 :(得分:1)
1)&x
中的obj(&x)
用作运营商的地址。
2)不,这是一个指针。它的时间是Object *
,而不是Object &
。
3)防止从可能有自己的类型转换操作符的不兼容指针类型进行转换。
C ++有三种可用的null:
NULL
- 已过时;仅用于检查返回指针的C函数的返回值0
- 已弃用;文字零在标准中定义为空指针nullptr
- 从C ++ 11开始,这是测试null的首选方法。此外,nullptr_t
是类型安全的null。答案 1 :(得分:1)
成员obj
的类型为Object*
,但构造函数需要引用。因此,要获取指针,必须应用地址运算符&
。并且该成员是一个指针,因为它可以是NULL(在默认构造函数中设置),并且引用永远不能为NULL。
私有成员不是const引用,而 poinetr 是const。它被取消引用以获得参考。
在这种特定情况下,我也看不到潜在隐式转换的任何负面影响。
答案 2 :(得分:0)
1)令牌&
有三个含义:
因此,了解您是在查看声明还是表达方式非常重要。
explicit Cref( const Object & x )
此处sigil出现在函数参数的声明中,这意味着参数x
的类型是对Object
const
的引用。
: obj ( &x ) {}
此处运算符用于成员初始值设定项表达式。成员obj
初始化为指向x
的指针。
2)由于成员obj
实际上是指针,因此需要取消引用运算符一元*
来获取引用。
3)一般来说,在任何(非复制)构造函数上使用explicit
是个好主意,它可以只接受一个参数。不幸的是,语言并不默认为显式,而是让你使用某种“隐式”关键字代替。在这种情况下,如果构造函数是隐式的,那么这可能会发生一件坏事:
Object create_obj();
void setup_ref(Cref& ref) {
ref = create_obj();
}
没有编译器错误或警告,但setup_ref
函数存储指向临时对象的指针,该函数在函数返回时无效!
答案 3 :(得分:0)
1)obj的类型不是引用,obj是指针,并且const指针必须用地址初始化,因此,必须应用address-of运算符&amp;。
2)get()方法返回的引用不是对类成员obj的引用,而是对obj指向的对象的引用,因此必须使用*来引用它。
3)关键字explicit意味着我们拒绝隐式转换,也就是说,我们告诉编译器,不要为我们使用这个构造函数进行隐式转换。
示例:
class Cref<Object> A;
Object B;
A=B;
没有显式就没关系 - 因为我们在右侧需要一个Cref对象,编译器将使用构造函数Cref(const Object&amp; B)自动创建一个Cref对象。但是如果你添加一个显式的,编译器就不会进行转换,就会出现编译错误。