2011-11-13 45 views
0

我在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; 
}; 

所以这里的重点是分配空/初始化一个常量引用。但我不确定我了解以下内容: 1.我们用另一个常量引用x初始化一个常量引用。但为什么它又作为obj(& x)完成?常量对象&中的& x与obj中的& x不同(& x)?我看到这一点,但不清楚为什么应该如此。请解释一下。 2. get方法() - 我们尝试返回该类的私有成员obj的const引用。它已经是一个const引用。为什么返回* obj而不仅仅是obj? 3.为什么显式的关键字?如果发生隐式类型转换,会发生什么情况?有人可以为此提供一个场景吗?

由于

回答

1
  1. 的构件objObject*型的,但构造函数采用一个参考。因此,要获取指针,必须应用地址 - 运算符&。而成员是一个指针,因为它可以是NULL(在默认构造函数中设置),并且引用永远不能为NULL。

  2. 私人构件是 const引用,但poinetr为const。它被取消参考。

  3. 在这个特定情况下,我看不到潜在隐式转换的任何负面影响。

+0

感谢您的澄清!特别是#2! :) – svk

+0

关于#1,这意味着这是一个声明的事情。由于我们只能在实际将其分配给指针时声明一个类似于const Object & x;的const引用,所以ptr =&x就不可避免地完成了。我的理由是否正确? – svk

+0

@SuprajaJayakumar:从逻辑的角度来看,一个参考文件基本上命名一个对象。也就是说,在构造函数中,传递给它的对象的名称为'x'(因为它是一个const引用,所以它是const的)。因此,您可以像使用该类型的变量一样使用'x'。为了得到一个指向变量的指针,你使用了addess-of运算符'&',因此你可以用'x'来完成。使用符号'&'定义引用的事实在逻辑上与此无关。如果他们决定为此使用关键字'ref',那就是一样了。 – celtschk

1

1)在obj(&x)&x被用作地址的运营商。

2)不,它是一个指针。它的时间是Object *,而不是Object &

3)防止从可能具有其自己的类型转换运算符的不兼容指针类型进行转换。

C++有可用空的三种口味:

  • NULL - 过时;仅用于检查返回指针的C函数的返回值
  • 0 - 不建议使用;在标准中将文字零定义为空指针
  • nullptr - 从C++ 11开始,这是测试null的首选方法。此外,nullptr_t是一个类型安全的null。
0

1)令牌&有三个含义:

  • 一元地址运算符:取任何左值表达式的地址,给人一种指针到该对象。
  • 参考信息:在声明中,是指参考类型。
  • 二进制位AND运算符 - 这里没有使用

所以知道你是否在寻找一个声明或表达很重要。

explicit Cref(const Object & x) 

这里印记出现在函数参数的声明,这意味着参数x的类型是一个Objectconst的参考。

: obj (&x) {} 

此处运算符用于成员初始值设定项表达式中。成员obj被初始化为指向x的指针。

2)由于成员obj实际上是一个指针,因此需要取消引用操作符一元运算符*来获取引用。

3)一般来说,在任何可以接受一个参数的构造函数上使用explicit是一个好主意。这很不幸,语言不会默认为显式的,并且当您的意思是让您使用某种“隐式”关键字时。在这种情况下,这里如果构造是隐含的可能发生的一个相当糟糕的事情:

Object create_obj(); 
void setup_ref(Cref& ref) { 
    ref = create_obj(); 
} 

没有编译器错误或警告,但setup_ref功能可存储一个指向临时对象,其中由时间是无效的函数返回!

0

1)obj的类型不是引用,obj是指针,const指针必须用地址初始化,所以必须应用操作符地址&。 2)get()方法返回的引用不是对类成员obj的引用,而是对obj指向的对象的引用,所以你必须使用*来表示它。 3)关键字显式意味着我们拒绝隐式转换,也就是说,我们告诉编译器,不要用这个构造函数对我们进行隐式转换。
例子:

class Cref<Object> A;
Object B;
A=B;

这是确定的,而不明确的 - 因为我们需要在右侧的Cref的对象,编译器会自动制作与Cref的构造函数(const对象& B)一个Cref的对象。但是如果你添加一个显式的,编译器不会进行转换,那么会出现编译错误。