简体   繁体   中英

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. 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?

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. 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". 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. 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.

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. Here, the name variable can be accessed within functions of the person class but not the doubleperson subclass. 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. 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. 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.

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). 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).

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; }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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