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

Posted

技术标签:

【中文标题】您可以强制从抽象基类继承的类仅具有在基本情况下定义的公共方法吗?【英文标题】:Can you force classes inheriting from abstract base class to only have the public methods defined in base case? 【发布时间】:2015-03-07 08:40:06 【问题描述】:

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

我不关心私有方法如何工作,但我想强制类只有一个公共方法。

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

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。我想防止这种情况发生。

【问题讨论】:

你为什么要这样做? 即使您可以做到这一点,也不会强迫开发人员仅通过该一种方法公开类的功能(这也是一个非常奇怪的目标)。 我不明白。如果我能做到这一点,如果子类只能有一个公共方法,开发人员怎么能以其他方式公开功能? 这个想法违背了整个继承/可重用的概念。我可以想象使用嵌套的私有类可以实现与您想要的类似的东西,但除非您明确说明您的动机,否则我们几乎无能为力。 @Alegnem:实际上,这个想法强化了这个概念。可以说 OP 直观地力求更严格地分离接口(公共函数)和实现(虚拟函数)。 【参考方案1】:

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

更新

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

class BTransform

private:
    MyObject B_Stuff(MyObject input);

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

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

【讨论】:

【参考方案2】:

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

它的全部意义在于,此层次结构中的所有类都旨在通过对基类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 所写的那样。正如赫伯萨特所说:

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

【讨论】:

【参考方案3】:

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

【讨论】:

以上是关于您可以强制从抽象基类继承的类仅具有在基本情况下定义的公共方法吗?的主要内容,如果未能解决你的问题,请参考以下文章

17.Python自学之路:面对过程编程之继承

面向对象程序设计——抽象基类,访问控制与继承,继承中的类作用域,拷贝函数与拷贝控制

为啥具有私有构造函数的类不阻止从此类继承?如何控制哪些类可以从某个基类继承?

具有数据成员的抽象基类

抽象类,派生类,继承

OOP1(定义基类和派生类)