繁体   English   中英

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

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

这可能是一个愚蠢的问题,但我一整天都在考虑这个问题。 创建派生类时,是否使用基类的公共成员对其自己的私有变量进行操作? 为了更好地解释这个,我在下面写了一个快速程序

#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();

当我运行此代码时,我得到了

bob
jon
jim
0032F904
0032F8E0
0032F8BC

这告诉我“name”变量有三个独立的实例。 当我创建一个基类时,c.setname是否在类person或类double person中使用setname,以及它如何知道从我的派生类而不是基类中对“name”进行操作?

您正在混淆访问权限与构建类的实例。

声明类时,您将定义新类型的结构。 这可以包括成员变量(和函数等),并且每次将类创建为对象时都会创建这些变量。 例如,如果您创建了3个不同的Person类变量,则每个变量对于在类定义中声明的每个成员变量都有自己的不同内存。 这有例外,例如静态成员变量,但通常每个类的实例都有自己的每个成员变量的内存空间。

创建子类只是将现有类有效地扩展为可包含新成员变量(和其他相关因素)的新类型。 父类的原始内存定义仍包含在子类中。 在这种情况下,您的doubleperson类包含与父person类相同的信息,即每个doubleperson类现在都有一个名为“name”的成员变量。 因此,当您创建每个doubleperson类的实例时,您将在内存中为此成员变量名称和doubleperson类的其他部分创建一个不同的位置。 这当然是您在每个实例中看到不同内存位置的原因。 如果你已经在person类中声明了成员变量名静态,那么现在将在doubleperson的所有实例(以及person)上共享一个变量,然后你会看到每个doubleperson实例具有相同的内存位置for成员变量名称。

这也是说成员变量的访问权限不反映它们如何存储在类定义中。 Access只定义类层次结构中的哪个级别,您可以访问特定的成员变量。 这里,name变量可以在person类的函数内访问,但不能在doubleperson子类中访问。 但是,无论何时创建doubleperson类的实例,都要将person类的定义与它一起放在自己独特的内存空间中。 要修改特定成员变量在实例中跨内存存储的方式,您需要查看“静态”或其他编程模式等关键字来实现此类功能。

我想我看到你的困惑。 构造时的doubleperson对象仍将调用person类的默认构造函数。 双重人员仍然是一个人,但只能公开访问其成员。 因此,使用getter和setter,doubleperson对象可以通过它可以访问的person对象公共方法访问person基础对象的私有变量。

另外,正如StoryTeller在上面的注释中指出的那样,你的getname方法按值返回(这是一个被销毁的临时副本。这不应该在启用了正确的警告的情况下编译)。 相反,你应该通过引用返回,如果你真的想要地址的名称方法(这有助于促进你的问题,3个单独的地址,但在这个问题之外也是不好的做法,打破封装)。

它应该是:(如上所述,这只能说明问题的重点,而且实际上是不好的做法,因为它破坏了封装)

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

暂无
暂无

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

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