简体   繁体   中英

strange c++ operator (operator unsigned short())

I run into a strange c++ operator.

http://www.terralib.org/html/v410/classoracle_1_1occi_1_1_number.html#a0f2780081f0097af7530fe57a100b00d

class Number {
.. 
    operator unsigned short () const;



};

I called this operator as: a Number(..); unsigned short b = a.operator unsigned short();

this works, but I can't understand how it works.

first, this operator don't have a return value. seconds, a.operator unsigned short() is really strange to me. What is a better way to call this?

if I call : unsigned short b = a; does the operator will get called? is there any c++ standard to say about this?

The function is a user defined conversion operator. More details can be found at http://en.cppreference.com/w/cpp/language/cast_operator .

You said,

this operator don't have a return value. seconds,

The return values of the user define conversion operators is the explicit type. In your case, the return type is unsigned short .

You asked:

What is a better way to call this?

You could do an explicit cast to invoke the function.

Number n;
unsigned short s = (unsigned short)v;

It is also called when an conversion is required by the compiler.

void foo(unsigned short s) {}

Number n;
foo(n);  // Number::operator unsigned short() is called to cast
         // n to an unsigned short.

You asked:

if I call : unsigned short b = a; does the operator will get called? is there any c++ standard to say about this?

Yes. The user defined operator function gets called.

Here's the relevant sections from the C++ Draft Standard (N3337):

12.3.2 Conversion functions

1 A member function of a class X having no parameters with a name of the form

...

[ Example:

 struct X { operator int(); }; void f(X a) { int i = int(a); i = (int)a; i = a; } 

In all three cases the value assigned will be converted by X::operator int(). end example ]

This is the conversion operator. A conversion function typically has the general form

operator type() const;

where type represents a type. It means objects of type Number can be converted to short int .

The conversion operator have no explicitly stated return type and no parameters, because the return type is exactly the type in the signature.

It's a conversion function, called to convert your type into a specific other type under various conditions, and it's covered in ISO C++11 12.3.2 Conversion functions .

In your case, it's called when the Number instance needs to be converted into an unsigned short .

By providing conversion operators, you can take full control over what happens during the conversion process, including such evil as the following:

#include <iostream>

struct X {
    int val;
    X(int v) { val = v; };
    operator int() { return val + 1; }; // pure evil
    friend std::ostream& operator<< (std::ostream&, X&);
};

std::ostream& operator<< (std::ostream &out, X &x) {
    out << x.val;
    return out;
}

int main (void) {
    X xyzzy (42);;
    std::cout << xyzzy << '\n';
    std::cout << (int)xyzzy << '\n';
    return 0;
}

which will output the value when you use the instance directly, but output something totally different when you cast it.

Now granted, that's rather evil and not a really good use case but you can use this for things such as rounding floats rather than truncating them, when converting to an integer:

#include <iostream>

struct X {
    double val;
    X(double v) { val = v; };
    operator int() { return (int)(val + 0.5); };
    friend std::ostream& operator<< (std::ostream&, X&);
};

std::ostream& operator<< (std::ostream &out, X &x) {
    out << x.val;
    return out;
}

#define E 2.718281828456
int main (void) {
    X xyzzy (E);
    double plugh = E;

    std::cout << plugh << " -> " << (int)plugh << '\n';
    std::cout << xyzzy << " -> " << (int)xyzzy << '\n';

    return 0;
}

The output of that code is:

2.71828 -> 2
2.71828 -> 3

As a supplement for the first answer, when you use keyword explicit , note the difference, using explicit would force the programmer to assert his intention to convert using a cast:

class Number {
private:
    int num;

public:
    explicit Number(int number) : num(number) {}  // constructor

    explicit operator unsigned short () const {  // conversion operator
        return num;
    }
};

int main() {
    Number classTypeNumber(10);
    // unsigned short convertToUshortNumber = classTypeNumber; // error
    // implicit conversion is not allowed.
    // now you should explicit convert the instance first.
    // typedef unsigned short int __u_short in types.h file.
    unsigned short convertToUshortNumber = static_cast<__u_short>(classTypeNumber); 
    cout << convertToUshortNumber;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM