Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

it is possible to change return type when override a virtual function in C++?

I encounter a problems about override virtual functions, in fact,it is about hessian (a web service protocol).

it has a base class Object, and some derived classes : Long,Int,String,...,all derived classes has a no-virtual function "value"

   class Object  
   {  
     ...    
   };  


   class Long :public Object  
   {  
       ...  
   public:  
       typedef long long  basic_type;  
       basic_type value(){return value_;}  
   private:  
       basic_type value_;  
       ...  
   };  


   class Int :public Object  
   {  
      ...  
   public:  
       typedef int basic_type;  
       basic_type value(){return value_;}  
   private:   
       basic_type value_;  
       ...  
   };  

now I want to add a function ,say, toString ,which can convert Object to a string:

Object *obj  = ...
cout<<obj->toString();

if I can change the value function to virtual ,I only need to write a toString function in Object, else, I need to write a virtual function toString, and to override this functions in all derived classes.

for example

   class Object  
   {  
       virtual Type value(); // It seemed that I can't write a function like this,because the Type is different for different derived classes  


       std::string toString()  
       {  
           some_convert_function(value());  
       }  

   };  

but I can't write a virtual value function because of return value can't be override.

is there any good solution for this issue?

Thanks

like image 905
camino Avatar asked Nov 19 '10 05:11

camino


People also ask

Can you change return type of virtual function?

You can override a member function with any return type as long as the return type is covariant. This "You can override a member function with any return type" is not correct. You can override as long as the return type is identical or covariant (which you explained), period.

Can you override a virtual function?

You can override virtual functions defined in a base class from the Visual Studio Properties window.

Can override function have different return type C++?

In C++, an overriding function in a derived class can't differ only by return type from a virtual function in a base class.

Is it necessary to override every virtual function?

It is not mandatory for the derived class to override (or re-define the virtual function), in that case, the base class version of the function is used.


1 Answers

it is possible to change return type when override a virtual function in C++?

Only in a very limited way, in that (raw) pointer or reference return type can be covariant.

is there any good solution for this issue?

Well, there are two fairly good solutions, and one slightly bad solution.

I'm giving you the slightly bad solution here. One reason that I'm giving that is that it's easy to understand, or at least it's quite easy to "copy and modify" even if one doesn't quite understand it. Another reason is that one of the good solutions requires some extensive general support machinery that there's no room for discussing here, and the other good solution (the one that in my opinion is best in nearly every respect) is of a kind that, at least when I have presented that kind of solution, has automatically received drive-by downvotes and only that, here on SO. I guess that that's the price to pay for the diversity here, which diversity is a Very Good Thing :-) But, unfortunately it means that there's no point in offering the real good stuff, I'd be down to negative rep then.

Anyways, code, based on dominance in virtual inheritance; it's about the same as inheriting an implementation of an interface in Java or C#:

#include <iostream>
#include <string>
#include <sstream>

//--------------------------------------- Machinery:

class ToStringInterface
{
public:
    virtual std::string toString() const = 0;
};

template< typename ValueProvider >
class ToStringImpl
    : public virtual ToStringInterface
{
public:
    virtual std::string toString() const
    {
        ValueProvider const&    self    =
            *static_cast<ValueProvider const*>( this );
        std::ostringstream      stream;
        stream << self.value();
        return stream.str();
    }
};

//--------------------------------------- Usage example:

class Object  
    : public virtual ToStringInterface
{  
    // ...    
};  

class Long
    : public Object
    , public ToStringImpl< Long >
{  
public:  
   typedef long long  BasicType;  
   Long( BasicType v ): value_( v ) {}
   BasicType value() const { return value_; }  
private:  
   BasicType value_;  
};  

class Int
    : public Object
    , public ToStringImpl< Int >
{  
public:  
   typedef int BasicType;  
   Int( BasicType v ): value_( v ) {}
   BasicType value() const { return value_; }
private:   
   BasicType value_;  
}; 

int main()
{
    Object const& obj = Int( 42 );
    std::cout << obj.toString() << std::endl;
}

If your Long and Int classes etc. are very similar, as they seem to be, consider defining just one class template, or perhaps inherit from specializations of such a template (this might also help avoid bugs, since it reduces redundancy).

EDIT: I see now that you have accepted an answer that is essentially just my last suggestion about templating. That means that I've answered the question as posed (a solution for distinct, different classes) while you had something less general in mind. Oh well.

Cheers & hth.,

like image 128
Cheers and hth. - Alf Avatar answered Oct 19 '22 15:10

Cheers and hth. - Alf