C++ 虚拟继承和访问 public 虚拟方法,其实现在继承受保护的 class 中

C++ virtual inheritance and access to a public virtual method whose implementation is in a class whose inheritance is protected

我正在使用虚拟继承来创建一个 class EditablePrimeNumberSet(一组素数),它继承了 class EditableNumberSet(一组可以递增的整数),同时仅公开base class NumberSet(一组数字)。 (我不希望我的 class 暴露方法 add 会导致一个不只包含质数的集合)

备注:这只是一个简单的例子。我实际上不研究素数。这个例子只是为了说明我面临的问题。

我的问题是,当我想在 EditableNumberSet 变量上调用虚方法 contains44 时,我需要 static_cast 它以避免编译错误。看起来编译器发现直接实现是易于处理的,因为它知道我的对象的实际类型,但随后发现此方法不可访问。所以,实际上,我并没有被卡住,但觉得这样做很好奇而且不优雅 static_cast。是否有一些改进我的代码的技巧?

using namespace std;

class NumberSet {
public :
    int size() {return myList.size();}
    virtual bool contains44()
    {
      cout << "in base method\n";
      return myList.count(44)>0;
    };
protected :
    set<int> myList;
};

class EditableNumberSet : public virtual NumberSet {
public :
    void add(int i) {myList.insert(i);}
    bool contains44() override
    {
        cout << "in inherited method\n";
        return false;
    } // 44 is not a prime number
};

class EditablePrimeNumberSet: public virtual NumberSet, protected EditableNumberSet {
public :
    void addNearestPrimeNumber(int i)
    {
        int j=0;
        //code that set j to the nearest prime number next to i...
        add(j);
    }
};

int main()
{
    EditablePrimeNumberSet listPN;
    listPN.addNearestPrimeNumber(45);
    listPN.NumberSet::contains44(); //  use base class method implementation
    static_cast<NumberSet &>(listPN).contains44(); // use derived class method implementation
    listPN.contains44(); //  error: ‘virtual bool EditableNumberSet::contains44()’ is inaccessible within this context
}

如果您想从受保护的 class 中公开单个名称,您可以使用 using 声明:

class EditablePrimeNumberSet : public virtual NumberSet, protected EditableNumberSet {
public:
    using EditableNumberSet::contains44; // Expose EditableNumberSet::contains44 as 
                                         // part of EditablePrimeNumberSet's public interface

    void addNearestPrimeNumber(int i)
    {
        int j = 0;
        //code that set j to the nearest prime number next to i...
        add(j);
    }
};

然后当您调用 listPN.contains44() 时,您调用继承的方法。