C++ 常量引用包装器

C++ 常量引用包装器,c++,pointers,constructor,constants,C++,Pointers,Constructor,Constants,我在马克·艾伦·韦斯的《数据结构》一书中看到了以下代码 template <class Object> class Cref { public: Cref ( ) : obj ( NULL ) { } explicit Cref( const Object & x ) : obj ( &x ) { const Object & get( ) const { if ( isNull( ) ) throw NullPointerException( ) ; e

我在马克·艾伦·韦斯的《数据结构》一书中看到了以下代码

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;
};
模板
类Cref
{
公众:
Cref():obj(NULL){}
显式Cref(常量对象和x):对象和x{
const对象&get()const
{
if(isNull())
抛出NullPointerException();
其他的
返回*obj;
}
bool isNull()常量
(返回obj==NULL;}
私人:
常量对象*obj;
};
因此,这里的要点是分配null/初始化常量引用。但我不确定我是否理解以下内容: 1.我们用另一个常量引用x初始化一个常量引用。但为什么它再次作为obj(&x)进行?常量对象中的&x与obj(&x)中的&x不同?我看到了这一点,但不太清楚为什么会这样。请解释。 2.get方法()-我们尝试返回此类的私有成员obj的常量引用。它已经是常量引用。为什么返回*obj而不仅仅是obj? 3.为什么使用显式关键字?如果发生隐式类型转换,会发生什么情况?有人能提供一个场景吗

谢谢

1)
obj(&x)
中的
&x
用作操作员的地址

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

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

C++提供了三种类型的null:

  • NULL
    -过时;仅用于检查返回指针的C函数的返回值
  • 0
    -已弃用;标准中将文本零定义为空指针
  • nullptr
    -从C++11开始,这是测试null的首选方法。此外,
    nullptr\t
    是类型安全的null
  • 成员
    obj
    的类型为
    Object*
    ,但构造函数采用引用。因此,要获取指针,必须应用运算符的地址
    &
    。成员是指针,因为它可以为NULL(在默认构造函数中设置),引用永远不能为NULL

  • 私有成员不是const引用,而是const的poinetr。它被取消引用以获得引用

  • 在这个特定的案例中,我也看不到潜在隐式转换的任何负面影响

  • 1) 标记
    有三种含义:

    • 运算符的一元地址:取任何左值表达式的地址,给出指向该对象的指针
    • 引用符号:在声明中,表示引用类型
    • 二进制位AND运算符-此处不使用
    因此,了解您是在看一个声明还是一个表达式是很重要的

    explicit Cref( const Object & x )
    
    这里,符号出现在函数参数的声明中,这意味着参数
    x
    的类型是对
    对象的引用,该对象是
    常量

    : obj ( &x ) {}
    
    这里,运算符用于成员初始值设定项表达式。成员
    obj
    初始化为指向
    x
    的指针

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

    3) 一般来说,在任何(非复制)构造函数上使用
    显式
    是一个好主意,它可以只接受一个参数。不幸的是,这种语言并没有默认为显式的,当你想要的时候,它会让你使用某种“隐式”关键字。在这种情况下,如果构造函数是隐式的,那么可能会发生一件非常糟糕的事情:

    Object create_obj();
    void setup_ref(Cref& ref) {
        ref = create_obj();
    }
    
    没有编译器错误或警告,但是
    setup\u ref
    函数存储指向临时对象的指针,该指针在函数返回时无效

    1)obj的类型不是引用,obj是指针,常量指针必须用地址初始化,因此必须应用运算符&的地址。 2) get()方法返回的引用不是对类成员obj的引用,而是对obj指向的对象的引用,因此必须使用*来遵从它。 3) 关键字explicit意味着我们拒绝隐式转换,也就是说,我们告诉编译器,不要使用此构造函数为我们进行隐式转换。
    例如:

    类别Cref A
    对象B
    A=B


    没有显式表达式也可以——因为我们需要右侧的Cref对象,编译器将使用构造函数Cref(constobject&B)自动生成Cref对象。但是如果添加显式,编译器将不会进行转换,将出现编译错误。

    感谢您的澄清!尤其是#2!:)关于#1,这意味着这是一个与声明有关的问题。因为我们只能声明一个const引用,比如const Object&x;当实际将其分配给指针时,ptr=&x不可避免地完成了。我的理由正确吗?@suprajayakumar:从逻辑的角度来看,引用基本上命名了一个对象。也就是说,在构造函数内部,传递给它的对象具有名称
    x
    (并且是常量,因为它是常量引用)。因此,使用
    x
    与使用该类型的变量完全相同。要获得指向变量的指针,可以使用运算符的加法,
    &
    ,因此对
    x
    也可以这样做。引用也是使用符号
    &
    定义的,这一事实在逻辑上与此无关。如果他们决定使用关键字
    ref
    ,情况也会一样。