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

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

本文关键字:基类 抽象 函数 返回类型 于多个 两个 实现      更新时间:2023-10-16

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

#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(),就没有什么模棱两可的,所以我认为它应该以某种方式工作,我想我只是还没有找到正确的符号。或者这是不可能的,如果是这样:为什么?

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

 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*时,将使用 ITestA_testtest() 的实现。当它投射到ITestB*时,即使是从ITestA* dynamic_cast,也会使用ITestB_test的实现。将打印以下程序:3.140

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

这有什么你能想到的缺点吗?

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

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

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