【问题标题】:Inheriting private members in C++在 C++ 中继承私有成员
【发布时间】:2011-02-10 05:04:27
【问题描述】:

假设一个类有私有数据成员,但 setter 和 getter 在公共范围内。如果你从这个类继承,你仍然可以调用那些 setter 和 getter——允许访问基类中的私有数据成员。既然提到派生类不能继承私有数据成员,这怎么可能

【问题讨论】:

  • 派生类确实继承私有数据成员。
  • 更令人困惑的是,您可以覆盖基类的私有虚函数。
  • @Space_C0wb0y:这一点也不令人困惑。它被称为模板方法模式(不幸的是,它与 C++ 模板无关)
  • 当您为属性添加 getter 和 setter 时,请务必重新考虑:有时它们非常好,但有时应该通过另一个更具描述性的界面来完成工作。

标签: c++ inheritance


【解决方案1】:

派生类不继承访问私有数据成员。但是,它确实继承了一个完整的父对象,其中包含该类声明的所有私有成员。

【讨论】:

  • @user265260:可能,但为什么呢?这让我觉得这是一个等待发生的问题。成员是私有的是有原因的,如果你可以玩弄他们的价值观,你就可以搞砸一个对象。此外,如果布局发生变化(并且它可以在不同的编译之间发生变化;具有size_t 成员的对象在 32 位和 64 位编译时可能具有不同的布局),您将踩到完全不同的数据。
  • @user265260:这可能适用于您的平台,但绝不是必需才能工作。永远。
  • 只是随便看看,我只是想知道这是如何实现的
  • 是的,您可以使用this 并相应地偏移,以一种骇人听闻的、不可移植的方式操纵私有数据。
  • @user265260:要了解“幕后”发生的事情,最好的方法是启动调试器并查看对象及其数据成员的地址。您还可以调出调试器的“内存”视图并查看数据在内存中的位置。请记住,您将看到的行为是特定于平台/编译器的。
【解决方案2】:

这取决于继承类型。如果您是私有继承,则派生类无法访问 Base 的私有成员。

Access                      public     protected    private
-----------------------------------------------------------
members of the same class      yes           yes        yes
members of derived classes     yes           yes         no
not members                    yes            no         no

【讨论】:

  • 我认为这个答案可能会产生误导或至少不准确。 @JRL 请尽量让它更清楚。
  • 这不能回答所提出的问题。
【解决方案3】:

因为 getter 和 setter 是 public - 任何人都可以调用它们,而不仅仅是派生类。

【讨论】:

  • 我的疑问是你怎么能操纵私有数据成员的值,因为显然你不能继承它们
  • 而那些getter和setter是基类的成员,所以他们可以访问私有数据。
  • @user235230:“显然你不能继承它们”这是错误的。
  • Adam 想要将他的汽车钥匙保密,所以只有他可以使用它们。甚至他的孩子也无法访问。但是,如果他为他的车钥匙提供公共获取方法,他就允许全镇的人顺便来开他的车兜风。 当然包括他的孩子。
  • 谢谢@David 这是我需要说服自己的东西
【解决方案4】:

它们被包括在内,但不被继承。这意味着:

  • 任何继承类型(: public SomeClass: protected SomeClass 甚至 : SomeClass,相当于 : private SomeClass)将不会使它们可以从子类方法或外部(this->asomeobject.a);
  • 它们仍会存在 - 占用为子类实例分配的内存空间;
  • 继承的方法将能够访问该私有字段。

因此,基本上protected 在外部不可见,而在内部和派生类中可见(如果未使用: private Parent),而private 在派生类和父类外部均不可见;它仅对父类的方法可见,即使它们被继承(但不被覆盖)。

【讨论】:

    【解决方案5】:

    您可以通过设置对 setter 和 getter 的访问权限来访问它们,并像这样访问它们

    *.h
    
    
    class Mamifere
    {
    private:
        int a;
    public:
        Mamifere();
        virtual ~Mamifere();
        int getA();
        // ~Mamifere(); //le delete dans le exp02() affiche seulement mamifere mort :( destructeur de la class mere 
        void manger() ;
        virtual void avancer() const;
    };
    
    
    class Deufin:public Mamifere{
    public:
        Deufin();
        void manger() const;
        void avancer() const;
        ~Deufin();
    };
    
    
    
    
    *.cpp
    
    Mamifere::Mamifere(){
            printf("nouveau mamifere est nee\n");
            this->a=6;
        }
    
    Mamifere::~Mamifere(){
            printf("mamifere Mort :(\n");
        }
    void Mamifere::manger() {
        printf("hhhh   je mange maifere %d\n",Mamifere::getA());
        }
    void Mamifere::avancer() const{
        printf("allez-y Mamifere\n");
    }
    
    Deufin::Deufin(){
        printf("nouveau Deufin  est nee\n");
    }
    int Mamifere::getA(){
        return this->a;
    }
    void Deufin::manger() const{
        printf("hhhh   je mange poisson\n");
    
    }
    void Deufin::avancer() const{
    
        printf("allez-y Deufin\n");
    }
    
    Deufin::~Deufin(){
        printf("Deufin Mort :(\n");
    }
    
    
    
    main.cpp
    
    
    
    
    
    void exp031(){
        Mamifere f;//nouveau mamifere est nee   //   nouveau Deufin  est nee
        Deufin d;
    
        f.avancer();//allez-y Deufin (resolution dynamique des lien  la presence de mot cle virtual)
        f.manger();//hhhh   je mange maifere (resolution static des lien pas de mot cle virtual)
        printf("a=%d\n",d.getA());//Deufin Mort :(   mamifere Mort :( (resolution static des lien  la presence de mot cle virtual) distructeur de class fille appel auromatiquement le destructeur de la class mere
    
    
    }
    
    int main(){
        exp031();
    
        getchar();
        return 0;
    }
    

    【讨论】:

      【解决方案6】:

      Getter 和 setter 不能让您完全控制私有数据成员。控件仍然在基类中。

      【讨论】:

        【解决方案7】:

        使用模式

        class MyClass {
          private: int a;
          public: void setA(int x) { a = x; }
          public: int getA() const { return a; }
        };
        

        似乎是面向对象的,并且具有封装性。

        但是正如您所注意到的,您仍然可以直接访问私有字段,而仅仅将 a 设为公开并直接访问它并没有什么好处。

        在 C++ 中像这样使用 getter 和 setter 并没有什么意义。

        【讨论】:

        • 实际上是这样。在 C# 中(例如),如果您决定在此处缓存对 a 的访问(假设实际上计算 a 需要做很多工作),您只需创建一个属性就可以了。但是,在 C++ 中,您必须将所有引用 MyClass.a 的代码替换为 MyClass.GetA();
        • 这个问题与 C++ 而不是 C# 有关。很多人认为为整数类型提供通用的 getter 和 setter 是明智之举 - 但事实并非如此。
        • “在 C++ 中像这样使用 getter 和 setter 并没有什么意义。”。允许不受限制地访问数据成员,除非通过定义明确的接口(例如 getter 和 setter),这使得跟踪错误成为一场噩梦。您需要查看设置该成员的所有位置,以尝试确定它为何具有意外值。通过定义明确的接口限制对类成员的访问使调试更加容易,因为堆栈跟踪提供了一些有用的洞察力。
        • @andand:或者你可以学习更好地使用你的调试器。
        • 这不能回答问题。这只是对个人对编程风格的看法的咆哮(实际上是一个不正确的结论)。
        猜你喜欢
        • 2020-09-01
        • 2011-02-26
        • 2020-09-04
        • 2018-05-11
        • 2012-01-04
        • 2023-03-03
        • 2011-09-26
        • 1970-01-01
        相关资源
        最近更新 更多