可以强制从抽象基类继承的类只在基类中定义公共方法吗

Can you force classes inheriting from abstract base class to only have the public methods defined in base case?

本文关键字:基类 定义 方法 抽象 继承      更新时间:2023-10-16

是否可以有一个抽象类,但FORCE实现类只能有抽象类中的公共方法?

我不在乎私有方法是如何工作的,但我想强制类只有一个公共方法。

例如,假设我有以下抽象类:

class MyObjectTransform
{
    public:
    virtual ~MyObjectTransform()
    {
    }
    virtual MyObject transform(MyObject input) = 0;
};

然后,我想强制所有从MyObjectTransform继承的对象只有一个(构造函数除外)公共方法transform。我不在乎继承类有什么私有方法。这可能吗?

更新:这里的目标是迫使开发人员只通过一个方法公开功能。例如,考虑这种情况:

class ATransform
{
private:
        MyObject A_Stuff(MyObject input);
public:
    override MyObject transform(MyObject input)
    {
        return this->A_stuff(input);
    }
};
class BTransform
{
public:
    MyObject B_Stuff(MyObject input);
    override MyObject transform(MyObject input)
    {
        return this->B_stuff(input);
    }
};

这里的问题是开发人员可以直接调用B_Stuff。我想防止这种情况发生。

不,你不能。派生类可以定义他们想要的任何公共成员函数。没有办法对此加以限制。

更新

如果您不希望用户访问B_Stuff,请将其声明为private。如果您希望从BTransform派生的类也可以使用它,请将它声明为受保护的

class BTransform
{
private:
    MyObject B_Stuff(MyObject input);
Public:     
    override MyObject transform(MyObject input)
    {
        return this->B_stuff(input);
    }
};

但是您不能使用C++语言强制声明B_Stuff为私有或受保护。必须将其定义为一项政策。

您已经在使用针对此场景的机制:它是抽象基类!

它的全部意义在于,该层次结构中的所有类都旨在支持通过对基类MyObjectTransform的指针/引用进行多态性使用。这样,用户就不知道实现类有什么公共方法,因为他只能使用通过基类可用的方法:transform

如果您想更严格地执行这一点,那么根本不要在头中公开实现类的声明。隐藏BTransformATransform,只公开工厂函数和抽象基类。

std::unique_ptr<MyObjectTransform> makeATransform()
{
    return { new ATransform };
}
std::unique_ptr<MyObjectTransform> makeBTransform()
{
    return { new BTransform };
}

这样,客户端/开发人员的代码看起来是这样的:

int main()
{
    auto btransform = makeBTransform();
    btransform->B_Stuff(input);   // ERROR, MyObjectTransform doesn't have this member function.
    btransform->transform(input); // FINE
}

用户只能使用基类中的一个公共方法。

当然,有人可以将指针投射到BTransform*,然后做任何他们想做的事情(前提是他们可以发现BTransform的实际实现是什么,因为我们隐藏了它)。但是,正如chmike所写的那样,为了防止public方法被访问,你必须将它们设置为private。正如赫伯·萨特所说:

C++保护墨菲,而不是马基雅维利

在C++中,公共函数应该是非虚拟的,而虚拟函数应该是私有的(析构函数除外)。应用这个准则会使问题完全消失,因为类的客户端只剩下一个公共函数可以调用:

class MyObjectTransform
{
    public:
    virtual ~MyObjectTransform()
    {
    }
    MyObject transform(MyObject input) // non-virtual!
    {
        // can do extra stuff, e.g. check input for validity
        doTransform(input);
    }
    private:
    virtual MyObject doTransform(MyObject input) = 0;
};
class ATransform : public MyObjectTransform
{
private:
    MyObject A_Stuff(MyObject input);
     MyObject doTransform(MyObject input) override
    {
        return this->A_Stuff(input);
    }
};
class BTransform : public MyObjectTransform
{
private:
    MyObject B_Stuff(MyObject input);
    MyObject doTransform(MyObject input) override
    {
        return this->B_Stuff(input);
    }
};