C++ 如何从基类公开继承,但在派生类中将基类的一些公共方法设为私有?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2986891/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 11:42:01  来源:igfitidea点击:

How to publicly inherit from a base class but make some of public methods from the base class private in the derived class?

c++

提问by powerboy

For example, class Basehas two public methods: foo()and bar(). Class Derivedis inherited from class Base. In class Derived, I want to make foo()public but bar()private. Is the following code the correct and natural way to do this?

例如,类Base有两个公共方法:foo()bar()。类Derived继承自类Base。在课堂上Derived,我想foo()公开但不bar()公开。以下代码是正确且自然的方法吗?

class Base {
   public:
     void foo();
     void bar();
};

class Derived : public Base {
   private:
     void bar();
};

回答by Brian R. Bondy

Section 11.3 of the C++ '03 standard describes this ability:

C++ '03 标准的第 11.3 节描述了这种能力:

11.3 Access declarations
The access of a member of a base class can be changed in the derived class by mentioning its qualified-id in the derived class declaration. Such mention is called an access declaration. The effect of an access declaration qualified-id ; is defined to be equivalent to the declaration using qualified-id

11.3 访问声明
基类成员的访问可以在派生类中通过在派生类声明中提及它的qualified-id 来改变。这种提及称为访问声明。访问声明qualified-id的效果;被定义为等同于使用qualified-id的声明

So there are 2 ways you can do it.

所以有两种方法可以做到。

Note: As of ISO C++ '11, access-declarations (Base::bar;) are prohibited as noted in the comments. A using-declaration (using Base::bar;) should be used instead.

注意:从 ISO C++ '11 开始,Base::bar;如注释中所述,禁止访问声明 ( )。using Base::bar;应该使用 using 声明 ( ) 来代替。

1) You can use public inheritance and then make bar private:

1)您可以使用公共继承,然后将 bar 设为私有:

class Base {
public:
    void foo(){}
    void bar(){}
};

class Derived : public Base {
private:
    using Base::bar;
};

2) You can use private inheritance and then make foo public:

2)您可以使用私有继承,然后将 foo 设为公共:

class Base {
public:
    void foo(){}
    void bar(){}
};

class Derived : private Base {
public:
    using Base::foo;
};

Note: If you have a pointer or reference of type Base which contains an object of type Derived then the user will still be able to call the member.

注意:如果您有一个 Base 类型的指针或引用,其中包含一个 Derived 类型的对象,那么用户仍然可以调用该成员。

回答by James McNellis

There is really no way to do what you want because if you derive publicly from Base, a user of the class will always be able to:

真的没有办法做你想做的事,因为如果你从 公开派生Base,该类的用户将始终能够:

Derived d;
Base& b = d;
b.bar();

It isn't "correct or natural" to make public base class functions inaccessible in a class derived publicy from the base class; instead, the base class interface should be refactored such that those functions are not public or are split into a separate class.

在从基类公共派生的类中使公共基类函数不可访问是不“正确或自然的”;相反,应该重构基类接口,使这些函数不公开或拆分为单独的类。

回答by vava

First, you have to understand what you want to do from the OOP perspective. There are two completely different types of inheritance:

首先,您必须从 OOP 的角度了解您想要做什么。有两种完全不同的继承类型:

  1. Inheritance of Interface. It is when you do implementin Java or other languages that have interfaces as standalone entities, it is also happens when you publically inherit from an empty abstract class in C++. Here you don't care about code at all but want to tell your compiler and everyone using you base/derived classes that this derived class is a special kind of you base class, it has allthe properties of base class, it behaves exactlyas base class does to the extent visible by the user of it, and can be used instead of the base class in any algorithms.

  2. Inheritance of the code. You have a piece of code in base class that you want to reuse in your derived class. Base class and derived class does not have to be related in any way, you just want to reuse code and that is it.

  1. 接口的继承。当您implement使用 Java 或其他将接口作为独立实体的语言时,当您从 C++ 中的空抽象类公开继承时也会发生这种情况。在这里你根本不关心代码,而是想告诉你的编译器和每个使用你的基/派生类的人,这个派生类是一种特殊的基类,它具有基类的所有属性,它的行为完全一样基类在用户可见的范围内执行,并且可以在任何算法中代替基类使用。

  2. 代码的继承。您在基类中有一段代码要在派生类中重用。基类和派生类不必以任何方式相关,您只想重用代码,仅此而已。

Public inheritance in C++ is the mix of both kinds, you get interface inheritance and you get code inheritance as well. Private inheritance is a different kind of beasts, you get onlycode inheritance, users of your derived class can not use it instead of base class and from the user perspective base and derived classes have no relation what-so-ever.

C++ 中的公共继承是两种类型的混合,您可以获得接口继承,也可以获得代码继承。私有继承是另一种野兽,您只能获得代码继承,派生类的用户不能使用它代替基类,从用户的角度来看,基类和派生类没有任何关系。

struct Base {};
struct PublicDerived : public Base {};
struct PrivateDerived: private Base {};

Base * base; PublicDerived * public_derived; PrivateDerived * private_derived;

base = public_derived; //good
base = private_derived; //compilation error.

Since you want to change the interface, you shouldn'tgo with public inheritance, by changing the interface you effectively saying that those two classes have different behavior and can not be used interchangeably. So what you really want is privately inherit and then make all the methods you want public and not the other way around.

既然你想改变接口,你不应该使用公共继承,通过改变接口你有效地说明这两个类具有不同的行为并且不能互换使用。所以你真正想要的是私下继承,然后将你想要的所有方法设为公开,而不是相反

回答by JohnMcG

According to the Liskov Substitution Principle, public inheritance should model "is-a." What you are saying with Derivedpublicly inheriting from Baseis that wherever Baseobject is required, an object of type Derivedwill do.

根据Liskov 替换原则,公共继承应该建模为“is-a”。您所说的Derived公开继承自是Base,无论何时Base需要对象,类型的对象Derived都可以。

If you requre Derivedto hide some operations that are available for Base, then what you are modeling is something other than "is-a," and public inheritance is not the correct tool.

如果您Derived需要隐藏一些可用于 的操作Base,那么您正在建模的不是“is-a”,并且公共继承不是正确的工具。

What you want is either private inheritance or composition, as other answers have detailed.

您想要的是私有继承或组合,正如其他答案所详述。

回答by wheaties

Let's say you have this:

假设你有这个:

class Foo{
public:
    void method1();
    void method2();
    void notGonnaSeeIt();
 private:
    //stuff
 };

To wrap it effectively you can either do a private inheritance and pass the methods you want to a public declaration like Brian suggested:

要有效地包装它,您可以执行私有继承并将您想要的方法传递给像 Brian 建议的公共声明:

class Bar : private Foo{
    void methodA(){ method1(); }
    void methodB(){ method2(); }
    //more stuff
};

or you can wrap it with a decorator

或者你可以用装饰器包装它

template<class T>
class Bar{
public:
    Bar(T *_input) : m_Input(_input){}
    void methodA() { m_Input->method1(); }
    void methodB() { m_Input->method2(); }
    //whatever else you need/want
private:
    T* m_Input;
};

Personally, I prefer the template way as it allows you to do the same thing with any class which inherits from Foo.

就个人而言,我更喜欢模板方式,因为它允许您对任何继承自Foo.

回答by Jason

If you don't need to treat it as the base class later and only need some functions of the base class, you could use composition rather than inheritance? (C# is my first language, but you get the idea)

如果以后不需要把它当基类,只需要基类的一些功能,可以用组合而不是继承吗?(C# 是我的第一语言,但你懂的)

class Base {
    public void foo();
    public void bar();
};

class Derived {
    private Base _base;

    public void bar() {
        _base.bar();
    }
};

回答by pcodex

with C++ 11 you could do the following:

使用 C++ 11,您可以执行以下操作:

class Base {
   public:
     void foo();
     void bar();
};

class Derived : public Base {
   private:
     using Base::bar;  

};

This ensures that Base::bar() is not accessible from outside the Derived class. It's ofcourse still accessible from outside the Base class.

这确保 Base::bar() 不能从 Derived 类外部访问。它当然仍然可以从 Base 类之外访问。