子类是否真的继承了私有成员变量?

Tor*_*enC 12 c++ inheritance private members

基本上据我所知,当你创建一个带有public,protected和private部分的基类以及每个public和protected部分中的变量/函数时,它们将被继承到子类的相应部分(由类子类定义) :私人基地,它将采取所有公共和受保护的基地成员并将其公开,将私人一词改为公开,将其全部公开,并将其更改为受保护,将其全部置于保护状态).

所以,当你创建一个子类时,你从来没有从前一个类的私有部分(在这种情况下是基类)中收到任何东西,如果这是真的那么子类的一个对象永远不应该拥有它自己的一个版本的私有变量或基类的函数是否正确?

让我们来看一个例子:

#include <iostream>

class myClass     // Creates a class titled myClass with a public section and a private section.
{
public:
  void setMyVariable();
  int getMyVariable();
private:
  int myVariable;     // This private member variable should never be inherited.
};

class yourClass : public myClass {};    // Creates a sub-class of myClass that inherits all the public/protected members into  the
// public section of yourClass. This should only inherit setMyVariable()
// and getMyVariable() since myVariable is private. This class does not over-ride any
// functions so it should be using the myClass version upon each call using a yourClass
// object. Correct?

int main()
{
  myClass myObject;           // Creates a myClass object called myObject.
  yourClass yourObject;       // Creates a yourClass object called yourObject
  yourObject.setMyVariable(); // Calls setMyVariable() through yourObject. This in turn calls the myClass version of it    because
  // there is no function definition for a yourClass version of this function. This means that this
  // can indeed access myVariable, but only the myClass version of it (there isn't a yourClass
  // version because myVariable is never inherited).

  std::cout << yourObject.getMyVariable() << std::endl;   // Uses the yourClass version of getMyVariable() which in turn
  // calls the myClass version, thus it returns the myClass myVariable
  // value. yourClass never has a version of myVariable Correct?

  std::cout << myObject.getMyVariable() << std::endl;     // Calls the myClass version of getMyVariable() and prints myVariable.

  return 0;
}

void myClass::setMyVariable()
{
  myVariable = 15;        // Sets myVariable in myClass to 15.
}

int myClass::getMyVariable()
{
  return myVariable;      // Returns myVariable from myClass.
}
Run Code Online (Sandbox Code Playgroud)

现在,理论上基于我的想法,这应该打印:15 15由于它只是总是使用myClass版本的函数(因此使用myClass myVariable).但奇怪的是,事实并非如此.运行此程序的结果打印:15 0这让我想知道,我们实际上不仅继承了myVariable,而且我们是否还有能力搞乱它?很明显,这是以某种方式创建myVariable的替代版本,否则myClass版本不会有0.我们确实通过这样做来编辑myVariable的第二个副本.

有人可以向我解释这一切,这已经撕裂了我对继承的理解.

did*_*erc 20

基本上据我所知,当你创建一个带有public,protected和private部分的基类以及每个public和protected部分中的变量/函数时,它们将被继承到子类的相应部分(由类子类定义) :私人基地,它将把基地的所有公共和私人成员公之于众,将私人一词改为公开,将其全部公开,并将其改为受保护,将其全部置于保护状态).

这句话有点混乱.

回想一下,在C++中为类和结构定义了继承.单个对象(即实例)不会从其他对象继承.使用其他对象构造对象称为组合.

当一个类继承自另一个类时,它从该类获取所有内容,但是继承字段的访问级别可能会禁止它们在继承者中使用.

此外,类有3种继承:( private默认)protected,和public.当子类继承时,它们中的每一个都会更改类属性和方法的访问级别.

如果我们以这种方式订购的访问级别:public,protected,private,从最小的保护,最受保护的,那么我们可以定义继承修饰符提高到至少水平,他们指定继承的类字段的访问级别,派生class(即继承的类).

例如,如果类B的类继承Aprotected传承修改:

  class B : protected A { /* ... */ };
Run Code Online (Sandbox Code Playgroud)

然后所有的字段A将至少具有以下protected级别B:

  • public字段变为protected(public级别提升到protected),
  • protected字段保持protected(相同的访问级别,所以这里没有修改),
  • private字段保持private(访问级别已经高于修饰符)


Bet*_*eta 9

"当你创建一个子类时,你永远不会从[基类]的私有部分收到任何东西.如果这是真的,那么子类的一个对象永远不应该拥有它自己的私有变量或函数版本上课,对吗?"

否.派生类继承基类的所有成员,包括私有成员.继承类的对象具有这些私有成员,但不具有对它们的直接访问权限.它可以访问可能有权访问这些成员的基类的公共成员,但它(派生类)可能没有具有此类访问权限的新成员函数:

class yourClass : public myClass
{
public:
  void playByTheRules()
  {
    setMyVariable(); // perfectly legal, since setMyVariable() is public
  }

  void tamperWithMyVariable()
  {
    myVariable = 20; // this is illegal and will cause a compile-time error
  }
};
Run Code Online (Sandbox Code Playgroud)


us2*_*012 7

myObject并且yourObject是两个不同的对象!他们为什么要分享什么?

想一想:忘掉继承,假设你有一个Person带有private int age;和的课public void setAge (int age) {...}.然后,您实例化两个对象:

Person bob;
Person bill;
bob.setAge(35);
Run Code Online (Sandbox Code Playgroud)

你现在也期待比尔现年35岁吗?你不会,对吧?同样,您myObject不与之共享其数据yourObject.


回应你的评论:

该类yourClass继承自myClass.这意味着这两个yourObjectmyObject拥有自己的myVariable,显然被定义后者,前者从继承myClass.


Anu*_*lia 6

从物理上讲,基类的每个成员(包括成员函数)都进入子类.如果他们是私人的并不重要.如果你公开地/保护地/私下地继承它们并不重要.所以在你的例子中,yourClass包含所有三个getMyVariable(),setMyVariable()myVariable.这一切都很简单,好吗?

重要的是我们如何访问它们.就像在系统上删除文件一样.因此,您应该首先了解不在那里的成员与在那里但不可访问的成员之间的区别.现在假设所有继承都是公开发生的.然后,基类的所有公共成员在派生类中是公共的,受保护的成员受到保护,私有成员不可访问.它们是不可访问的,并且不存在,因为在基类的受保护和公共部分中可以有一些成员函数访问基类的私有成员.因此,我们需要所有那些由base的公共和受保护成员函数访问的基本私有成员,以实现其功能.由于我们无法以简单的方式确定哪个成员函数需要哪个成员,因此我们在派生类中包含基类的所有私有成员.所有这些只是意味着在派生类中,私有成员只能通过基类的成员函数进行修改.

注意:每个私有成员都必须通过公共/受保护的meber函数直接或间接[通过另一个私有成员函数进行访问,而这些函数由公共/受保护成员函数调用],否则它没有用处.

因此,我们知道基类的私有成员变量在派生类中的用途,即其公共/受保护成员函数的功能.但是它们不能直接在基类中访问.

现在,我们将注意力转向私人/公共继承.对于公共继承,这意味着基类的所有可访问成员(即公共成员和受保护成员)不能处于比公共更宽松的级别.由于公众是最宽松的级别,公众和受保护的成员仍然是公开的.但是在受保护和私有继承中,两者分别在派生类中变为受保护和私有.在后一种情况下,由于所有这些成员都是私有的,因此无法在层次结构链中进一步访问它们,但是可以由给定的派生类访问它们.

因此,派生类中每个基类成员的级别是派生类()和继承类型(公共/受保护/私有)中它们的级别中的较小者.

同样的概念适用于课外的功能.对于他们来说,私人和受保护的成员是不可访问的,但它们确实存在并且可以由公共成员函数访问.

并以您的情况作为最后一个示例,setMyvariable()getMyVariable()可以myVariable在派生类中进行访问.但是派生类中没有指定的函数可以访问myVariable.修改你的课程:

class myClass
{
public:
  void setMyVariable();
  int getMyVariable();
private:
  int myVariable;
};

class yourClass : public myClass
{
public:
  // void yourFunction() { myVariable = 1; }
  /*Removing comment creates error; derived class functions can't access myVariable*/
};
Run Code Online (Sandbox Code Playgroud)

此外:您还可以为继承类型添加例外,例如私有继承,除了在派生类中公开的成员.但这完全是另一个问题.


Oli*_*rth 5

你永远不会打电话myObject.setMyVariable(),所以myObject.getMyVariable()不会回来15.

private并不意味着static.