Search code examples
c++classreturndefault

Default return of class instance without member function


Is it possible to make a class return a particular member variable by default when the object is used somewhere(without using a getter member function)?

If I have this class:

class A{
    public: 
       A(int nr) : number(nr){};
       ~A();
       int getNr(){ return this->number };
       int number;
};

To set and get its number later in the program, I can do this:

int main(){
    A thing(23);
    std::cout<<"Your number is: "<<thing.getNr();
    return 0;
}

But what I would like to do is this:

std::cout<<"Your number is: "<<thing;

And get the exact same result, make it return the member variable "number" by default. Can this be done/set somehow?

I know somebody might be thinking "Why not just use integers as they are for that?" - I'm making a class which should be able to "turn into" any type and then act like the assigned type, it would be nice if I could make it act like ints, doubles, strings in that regard too later.


Solution

  • Your specific example invokes the << stream insertion operator on an A. This operator can be overloaded to do what you want:

    #include <iostream>
    
    class A{
        public: 
            A(int nr) : number(nr) { }
            ~A() { }
            int getNr() const { return this->number; }
            int number;
    };
    
    std::ostream& operator<<(std::ostream& os, const A& a) {
        os << a.getNr();
        return os;
    }
    
    int main(int, char *[]) {
        A a(42);
        std::cout << a << std::endl; // prints 42
    }
    

    Note here I have made some other minor fixes to your code (fixed a missing ; and removed some unnecessary ones; added const to getNr()).

    For other situations, such as passing arguments of type A to functions that accept parameters of a different type, you can define user-defined conversion operators that are called by the compiler to convert an A to a different type. For example:

    void doSomething(int x) {
        // ...
    }
    
    class A{
        public: 
            A(int nr) : number(nr){}
            ~A(){}
            int getNr(){ return this->number; }
            int number;
            operator int() { return getNr(); }
    };
    
    int main(int, char *[]) {
        A a(42);
        doSomething(a); // calls operator int() above
        return 0;
    }
    

    Be careful with user-defined conversion operators. In particular, it's often best to mark them explicit and use static_cast<T>() to trigger the conversion. Implicit conversions can quickly get you into trouble with overload resolution.