您是否可以强制从抽象基类继承的类仅具有在基本情况下定义的公共方法?

时间:2015-03-07 08:40:07

标签: c++ c++11 inheritance abstract-class

是否可以使用抽象类,但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。我想阻止这一点。

3 个答案:

答案 0 :(得分:5)

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

<强>更新

如果您不希望用户访问它,则将B_Stuff声明为私有。如果您希望从BTransform派生的类也可以使用它,则将其声明为 protected

class BTransform
{
private:
    MyObject B_Stuff(MyObject input);

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

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

答案 1 :(得分:4)

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

这一点的重点在于,此层次结构中的所有类都旨在支持通过指向基类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的实际实现是什么,因为我们隐藏了它)。但是,没有绕过这样一个事实,即为了阻止public方法被访问,你必须让它们private,就像chmike写的那样。正如Herb Sutter所说:

  

C ++防止墨菲,而不是马基雅维利

答案 2 :(得分:1)

在C ++中,公共函数应该是非虚拟的,虚函数应该是私有的(析构函数除外)。应用此guideline会使您的问题完全消失,因为只有一个公共函数可供该类的客户调用:

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