简体   繁体   English

在C ++中,是为派生类创建的一组新的私有变量吗?

[英]In C++, are a new set of private variables created for a derived class?

This might be a stupid question but I've been thinking about it all day. 这可能是一个愚蠢的问题,但我一整天都在考虑这个问题。 When a derived class is created, is it using public members of the base class to act on its own private variables? 创建派生类时,是否使用基类的公共成员对其自己的私有变量进行操作? To explain this better I wrote a quick program below 为了更好地解释这个,我在下面写了一个快速程序

#include <iostream>
#include <string>

class person
{
public:
    std::string getname(void) { return name; }
    void setname(std::string x) { name = x; }
private:
    std::string name;
    int age;

};

class doubleperson :public person{};

int main()
{
    person a, b;
    doubleperson c;
    a.setname("bob");
    b.setname("jon");
    c.setname("jim");

    std::cout << a.getname() << std::endl;
    std::cout << b.getname() << std::endl;
    std::cout << c.getname() << std::endl;

    std::cout << &c.getname() << std::endl;
    std::cout << &a.getname() << std::endl;
    std::cout << &b.getname() << std::endl;

    std::cin.get();

When I run this code I get 当我运行此代码时,我得到了

bob
jon
jim
0032F904
0032F8E0
0032F8BC

Which tells me that there are three separate instances of the "name" variable. 这告诉我“name”变量有三个独立的实例。 When I create a base class, does c.setname use setname in class person or class double person and how does it know to act on "name" from my derived class instead of the base class? 当我创建一个基类时,c.setname是否在类person或类double person中使用setname,以及它如何知道从我的派生类而不是基类中对“name”进行操作?

You're confusing access privledges with building an instance of a class. 您正在混淆访问权限与构建类的实例。

When you declare a class, you are defining the structure of a new type. 声明类时,您将定义新类型的结构。 This can include member variables (and functions, etc.), and these would be created each time the class is created as an object. 这可以包括成员变量(和函数等),并且每次将类创建为对象时都会创建这些变量。 For example, if you created 3 different variables of class Person, each of these would have their own distinct memory for each of the member variables declared in the class definition. 例如,如果您创建了3个不同的Person类变量,则每个变量对于在类定义中声明的每个成员变量都有自己的不同内存。 There are exceptions to this, such as static member variables, but in general each instance of a class will have its own memory space of each of its member variables. 这有例外,例如静态成员变量,但通常每个类的实例都有自己的每个成员变量的内存空间。

Creating a subclass is just effectively extending an existing class into a new type that can include new member variables (and other related factors). 创建子类只是将现有类有效地扩展为可包含新成员变量(和其他相关因素)的新类型。 The original memory definition of the parent class is still contained within the subclass. 父类的原始内存定义仍包含在子类中。 In this case, your doubleperson class contains the same information as the parent person class, namely each doubleperson class now has a member variable called "name". 在这种情况下,您的doubleperson类包含与父person类相同的信息,即每个doubleperson类现在都有一个名为“name”的成员变量。 Hence, when you create an instance of each doubleperson class, you create a distinct location in memory for this member variable name and the other parts of the doubleperson class. 因此,当您创建每个doubleperson类的实例时,您将在内存中为此成员变量名称和doubleperson类的其他部分创建一个不同的位置。 This is of course why you see distinct memory locations in each of the instances. 这当然是您在每个实例中看到不同内存位置的原因。 If you had declared the member variable name in the person class static, this would now make one variable shared across all instances of doubleperson (and person, for that matter), and then you would have seen each doubleperson instance having the same memory location for the member variable name. 如果你已经在person类中声明了成员变量名静态,那么现在将在doubleperson的所有实例(以及person)上共享一个变量,然后你会看到每个doubleperson实例具有相同的内存位置for成员变量名称。

This is also to say access privlidges of member variables is not reflective of how they are stored in a class definition. 这也是说成员变量的访问权限不反映它们如何存储在类定义中。 Access just defines at what level in the class hierarchy you can access a particular member variable. Access只定义类层次结构中的哪个级别,您可以访问特定的成员变量。 Here, the name variable can be accessed within functions of the person class but not the doubleperson subclass. 这里,name变量可以在person类的函数内访问,但不能在doubleperson子类中访问。 But whenever you create an instance of the doubleperson class, you carry the definition of the person class along with it in its own distinct memory space. 但是,无论何时创建doubleperson类的实例,都要将person类的定义与它一起放在自己独特的内存空间中。 To modify how a particular member variable is stored in memory across instances, you need to look to keywords like "static" or other programming patterns to implement this type of functionality. 要修改特定成员变量在实例中跨内存存储的方式,您需要查看“静态”或其他编程模式等关键字来实现此类功能。

I think I see your confusion. 我想我看到你的困惑。 A doubleperson object when constructed will still call the default constructor of the person class. 构造时的doubleperson对象仍将调用person类的默认构造函数。 A doubleperson is still a person but only has public access to its members. 双重人员仍然是一个人,但只能公开访问其成员。 So using your getter and setters, a doubleperson object has access to the private variables of the person base object through the person object public methods it has access to. 因此,使用getter和setter,doubleperson对象可以通过它可以访问的person对象公共方法访问person基础对象的私有变量。

Also, as was pointed out by StoryTeller in the comments above, your getname method returns by value (which is a temporary copy that gets destroyed. This should not compile with the proper warnings enabled). 另外,正如StoryTeller在上面的注释中指出的那样,你的getname方法按值返回(这是一个被销毁的临时副本。这不应该在启用了正确的警告的情况下编译)。 Instead you should return by reference if you really want the address to the name method (which helps facilitate your question as to the 3 separate addresses, but outside of this question would also be bad practice and break encapsulation). 相反,你应该通过引用返回,如果你真的想要地址的名称方法(这有助于促进你的问题,3个单独的地址,但在这个问题之外也是不好的做法,打破封装)。

It should be: (which as noted above only helps to illustrate the point of your question and is really bad practice because it breaks encapsulation) 它应该是:(如上所述,这只能说明问题的重点,而且实际上是不好的做法,因为它破坏了封装)

std::string& getname(void) { return name; }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM