3

Is it possible to inherit identically named operator which only differ in return type, from two different abstract classes. If so, them:

  • what is the syntax for implementing operators

  • what is the syntax for using/resolving operators

  • what is the overhead in general case, same as for any other virtual function?

if you can provide me with a reference or sample code that would be helpful

thanks

12struct abstract_matrix {
 13    virtual double& operator()(int i, int j);
 14};
 15
 16    struct abstract_block_matrix {
 17        virtual double* operator()(int i, int j);
 18    };
 19
 20struct block_matrix : abstract_matrix, abstract_block_matrix {
 21
 22};

block matrix needs to provide implementations for both operators, so that it is either a matrix or a block matrix, depending on the context. I do not know how to provide implementation specific to block_matrix class. right now, it is done by passing object wrapped type as the last argument, but that does not seem very clean. I would like to retain pure matrix notation.

Anycorn
  • 50,217
  • 42
  • 167
  • 261
  • 2
    What do you mean by "virtual classes"? Do you mean virtual inheritance? A code sample of what you mean (even if it doesn't compile) would be helpful. – Terry Mahaffey Jan 01 '10 at 23:10

3 Answers3

1

You can't overload on the return type. When a function or an operator is invoked the compiler has to know which one to call. It will not infer that based on what the function(operator) call assigned to.

Looks like your are looking to implement some matrix math. Perhaps if you download DirectX SDK or OpenGL and have a look how they do it, you might get some ideas on how to do it properly.

Igor Zevaka
  • 74,528
  • 26
  • 112
  • 128
  • i know return types are not overloadable. However it does not seem to be a case with *inheritance*, at any rate compiler does not complain. my matrix requirements are different, ublas does not quite fit either – Anycorn Jan 01 '10 at 23:46
1

The return type of a function is not part of it's signature, so you can't have two operator+(i,j)'s in block_matrix - that would be an ambiguous call. So multiple inheritance is sort of a red herring here on this point. You just can't do that.

What are you really trying to do, and why?

In any event, for your other question: virtual operators are exactly like virtual functions in terms of performance and the way they operate. There are just slight semantic differences in how you use them - but under the hood they're just functions like any other.

Terry Mahaffey
  • 11,775
  • 1
  • 35
  • 44
  • I do not think so. In one case you are overriding abstract_matrix:: operator, in other case you are overriding abstract_block_matrix:: operator.so in principle I think there is a way to do it. I have have two workarounds but there are the ugly. – Anycorn Jan 02 '10 at 00:23
  • No, what I said was correct. There is no way to have a class with two identical functions differing only by return type. The "workaround" is to have them differ by more than the return type. – Terry Mahaffey Jan 02 '10 at 00:44
  • check this out. Class A has function f, A::f. Class B also has function f, B::f. Now C inherits A and B. So now C has access to A::f and B::f. The syntax for overriding either A or B straightforward. So you have access to both f, depending if C is either A or B, but not both through the same cast of object. If both parents abstract, then C can be derived via intermediate partially abstract class. – Anycorn Jan 02 '10 at 01:03
  • Yes. And if you call C::f in that case, you get a compiler error about an ambiguous call. Which is what I've been saying. – Terry Mahaffey Jan 02 '10 at 01:12
  • right. Is it possible to skip intermediate class and define both A::f and B::f in one place? – Anycorn Jan 02 '10 at 01:16
  • In the same class? No. You can not overload a function based on the return type. – Terry Mahaffey Jan 02 '10 at 04:21
0

I got it work, but it's wonky. I do love templates.

template<class T>
class Base1
{
};

template<class T>
class Base2
{
};

class Derived;
template<>
class Base1<Derived>
{
public:
     double foo(){return 0.1;}
};

template<>
class Base2<Derived>
{
public:
    int foo(){return 1;}
};

class Derived
    : public Base1<Derived>
    , public Base2<Derived>
{
public:
    using Base1<Derived>::foo;
};

int main()
{
     double sum = 0;
     Derived d;
     sum += d.foo(); //+ .1
     Base1<Derived> * pI = &d;
     sum += pI->foo(); //+ .1

     Base2<Derived> * pF = &d;
     sum += pF->foo(); //+ 1

     return (sum*10);
}

I couldn't get it to work without templates, although it seems like it should be able to. I'm not sure if you can get away with just doing templated member functions in the same manner, but my gut says "no".

In terms of code organization, I would then define the Base# stuff right after the definition or declaration of Derived, since that's really what it's for. Keep in mind you can then use typename Base1<Derived> something to make things prettier.

Edit: Oh, right! It doesn't allow you to do the "using" trick or have different return types, but it's otherwise simpler:

class Derived
    : public Base1
    , public Base2
{
    double Base1::foo(){...}
    double Base2::foo(){...}
}

There may be a terrible, horrible, awesome way to combine these two approaches, but I don't think it'll actually help out when using the code. I may get back to you on that.

Narfanator
  • 5,595
  • 3
  • 39
  • 71
  • I don't understand what you are doing, but a qualified name cannot be used to declare a member function as in: `double Base1::foo(){...} ` – curiousguy Nov 01 '11 at 02:16