由于多个抽象基类,实现两个具有相同名称但不同的非协变返回类型的函数

时间:2012-07-07 03:09:47

标签: c++ multiple-inheritance virtual-functions function-overriding abstract-base-class

如果我有两个抽象类定义一个具有相同名称但不同的非协变返回类型的纯虚函数,我如何从这些函数派生并为它们的函数定义一个实现?

#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;
}

只要我不直接调用C :: test()就没有任何歧义,所以我认为它应该以某种方式工作,我想我还没找到正确的符号。或者这是不可能的,如果是这样的话:为什么?

3 个答案:

答案 0 :(得分:3)

好的,这是可能的,而且方式也不是太难看。我必须添加一个额外的继承级别:

 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

现在C没有函数test(),但在向C*投射ITestA*时,将使用test()ITestA_test的实现。将其投放到ITestB*时,即使是来自ITestA*的dynamic_cast,也会使用ITestB_test的实现。 以下程序打印: 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;
}

这有你能想到的任何缺点吗?

答案 1 :(得分:2)

当您声明ITestA *a = new C()时,您已创建了一个C对象。如果使用test在其上调用a->test(),则必须使用C虚拟表来查找要执行的代码。但是C正在尝试使用相同签名test()的两种不同实现,这是不允许的。您将其声明为ITestA *的事实不会影响方法解析。您声明了方法virtual,因此无论您用于访问它的指针类型如何,都可以通过对象的实际类型找到它们。

您不能拥有两个具有相同名称和参数类型的方法。您需要找到构建此代码的另一种方法。

答案 2 :(得分:0)

我不认为这是可能的。函数按名称(和签名)重载。