问题描述:

I came across the following piece of code in the book on data structures by 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;

};

So the point here is to assign null/initialize a constant reference. But I am not sure I understand the following:

1. We initialize a constant reference with another constant reference x. But why is it again done as obj(&x) ? the & in const Object & x is different from the &x in obj(&x) ? I see this but not very clear why it should be so. Pls explain.

2. The get method() - We try to return a const reference of the private member obj of this class. It is already a const reference. Why return *obj and not just obj ?

3. Why explicit keyword ? What might happen if an implicit type conversion takes place ? Can someone provide a scenario for this ?

Thanks

网友答案:
  1. The member obj is of type Object*, but the constructor takes a reference. Therefore to get a pointer, the address-of operator, &, has to be applied. And the member is a pointer because it can be NULL (set in the default constructor), and references never can be NULL.

  2. The private member is not a const reference, but a poinetr to const. It is dereferenced to get a reference.

  3. In this specific case, I cannot see any negative effect of a potential implicit conversion either.

网友答案:

1) &x in obj(&x) is used as the address-of operator.

2) No, it is a pointer. Its time is Object *, not Object &.

3) To prevent casting from incompatible pointer types which might have their own type-cast operator.

C++ has three flavors of null available:

  • NULL - obsolete; use it only for checking the return values of C functions which return pointers
  • 0 - deprecated; the literal zero is defined in the Standard to be the null pointer
  • nullptr - as of C++11, this is the preferred way of testing for null. Furthermore, nullptr_t is a type-safe null.
网友答案:

1) The token & has three meanings:

  • Unary address-of operator: Take the address of any lvalue expression, giving a pointer to that object.
  • Reference sigil: In a declaration, means a reference type.
  • Binary bitwise AND operator - not used here

So it's important to know whether you're looking at a declaration or an expression.

explicit Cref( const Object & x )

Here the sigil appears in the declaration of a function parameter, meaning the type of parameter x is a reference to an Object which is const.

: obj ( &x ) {}

Here the operator is used in a member initializer expression. Member obj is initialized to be a pointer to x.

2) Since member obj is actually a pointer, the dereference operator unary * is needed to get a reference.

3) In general, it's a good idea to use explicit on any (non-copy) constructor which can take exactly one argument. It's just unfortunate that the language doesn't default to explicit and make you use some sort of "implicit" keyword instead when you mean to. In this case, here's one rather bad thing that could happen if the constructor were implicit:

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

No compiler error or warning, but that setup_ref function stores a pointer to a temporary object, which is invalid by the time the function returns!

网友答案:

1) The type of obj is not a reference, obj is a pointer, and a const pointer must be initialized with a address, so, the address-of operator, &, must be applied. 2) The reference the get() method returns is not a reference to the class member obj, but a reference to the object which obj points, so you have to use * to deference it. 3) The keyword explicit means we reject the implicit conversions, that is, we tell the compiler, don't make implicit conversions with this constructor for us.
Example:

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

It's OK without the explicit--Since we need a Cref object on the right side, the compiler will automate making a Cref object with constructor Cref( const Object & B ). But if you add an explicit, the compiler won't make conversions, there will be a compiling error.

相关阅读:
Top