簡體   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