Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implement two functions with the same name but different, non-covariant return types due to multiple abstract base classes

If I have two abstract classes defining a pure virtual function with the same name, but different, non-covariant return types, how can I derive from these and define an implementation for both their functions?

#include <iostream>

class ITestA {
    public:
        virtual ~ITestA() {};
        virtual float test() =0;
};

class ITestB {
    public:
        virtual ~ITestB() {};
        virtual bool test() =0;
};

class C : public ITestA, public ITestB {
    public:
    /* Somehow implement ITestA::test and ITestB::test */
};


int main() {
    ITestA *a = new C();
    std::cout << a->test() << std::endl; // should print a float, like "3.14"
    ITestB *b = dynamic_cast<ITestB *>(a);
    if (b) {
        std::cout << b->test() << std::endl; // should print "1" or "0"
    }
    delete(a);
    return 0;
}

As long as I don't call C::test() directly there's nothing ambiguous, so I think that it should work somehow and I guess I just didn't find the right notation yet. Or is this impossible, if so: Why?

like image 352
Tar Avatar asked Jul 07 '12 03:07

Tar


People also ask

Can we define two functions that have the same name but different parameter types?

Function overloading is a feature of object-oriented programming where two or more functions can have the same name but different parameters. When a function name is overloaded with different jobs it is called Function Overloading.

Can we have two functions with the same name but with different numbers of parameters in a single C program?

In C you can't have two functions with the same name, at all. In C++, it's entirely possible as long as the function function signature is different, ie two functions having the same name but different set of parameters.

What is it called when the same function name is used by different function declaration definitions with varying sets of parameters?

Rules in function overloading The same function name is used for more than one function definition. The functions must differ either by the arity or types of their parameters.

Can two functions have the same parameter?

Yes, its possible to use the same parameter name several times, given parameters have local scope. But i wouldn't define it as fine, function names, variable names, parameters and so forth should have logic names, this makes the code so much more understandable and easier to read.


1 Answers

Okay, it is possible, and the way isn't too ugly. I have to add an additional level of inheritance:

 ITestA       ITestB     <-- These are the interfaces C has to fulfill, both with test()
    |           |
ITestA_X     ITestB_X    <-- These classes implement the interface by calling a
    |           |             function with a different name, like ITestA_test
    \__________/              which is in turn pure virtual again.
         |
         C               <--  C implements the new interfaces

Now C has no function test(), but when casting a C* to an ITestA*, the implementation of test() in ITestA_test will be used. When casting it to an ITestB*, even by a dynamic_cast from the ITestA*, the implementation of ITestB_test will be used. The following program prints: 3.14 0

#include <iostream>

class ITestA {
    public:
        virtual ~ITestA() {};
        virtual float test() =0;
};

class ITestB {
    public:
        virtual ~ITestB() {};
        virtual bool test() =0;
};

class ITestA_X : public ITestA {
    protected:
        virtual float ITestA_test() =0;
        virtual float test() {
            return ITestA_test();
        }
};

class ITestB_X : public ITestB {
    protected:
        virtual bool ITestB_test() =0;
        virtual bool test() {
            return ITestB_test();
        }
};

class C : public ITestA_X, public ITestB_X {
    private:
        virtual float ITestA_test() {
            return 3.14;
        }
        virtual bool ITestB_test() {
            return false;
        }
};

int main() {
    ITestA *a = new C();
    std::cout << a->test() << std::endl;
    ITestB *b = dynamic_cast<ITestB *>(a);
    if (b) {
        std::cout << b->test() << std::endl;
    }
    delete(a);
    return 0;
}

Does this have any drawbacks you could think of?

like image 177
Tar Avatar answered Oct 19 '22 09:10

Tar