簡體   English   中英

C++ | 派生 class 正在訪問基 class 的私有成員而不是它自己的私有成員

[英]C++ | Derived class is accessing private members of the base class rather than its own private members

抱歉,如果這是一個明顯的問題,但我已經四處搜索,但我仍然不清楚如何解決這個問題。 這是我的代碼:

#include <iostream>
#include <string>
using namespace std;

class PermMagnet {
public:
    string name;
    int ac_rating;
    int dc_rating;
    int mass_kg;
    int age;
    PermMagnet(){
        // default constructor
        name = "";
        ac_rating = 0; dc_rating = 0;
        mass_kg = 0; age = 0;
    }
    PermMagnet(string c_name, int c_ac_rating, int c_dc_rating, int c_mass_kg, int c_age){
        // parameterised constructor
        name = c_name;
        ac_rating = c_ac_rating;
        dc_rating = c_dc_rating;
        mass_kg = c_mass_kg;
        age = c_age;
    }
    string get_owner(){
        return owner;
    }
    string get_classifier(){
        return classifier;
    }
    int get_coil_count(){
        return coil_num;
    }
protected:
    string location = "facility hall";
private:
    string owner = "Unspecified Staff";
    string classifier = "MAG-DP-";
    const int coil_num = 2;
};

class ElecMagnet : public PermMagnet {
public:
    // inherit base class constructors
    using PermMagnet::PermMagnet;

    string get_location(){
        return location;
    }

private:
    string owner = "Specified Staff";
    string classifier = "MAG-QD-";
    const int coil_num = 4;
};

int main() {

    // Create object using default constructor
    PermMagnet perm1;
    cout << "'perm1' age: " << perm1.age << endl;

    // Create object using parameterised constructor
    PermMagnet perm2("PermMagnet 2", 380, 400, 1500, 35);
    cout << "'perm2' age: " << perm2.age << " | 'perm2' name: " << perm2.name << endl;
    cout << "Owner of 'perm2': " << perm2.get_owner() << endl;
    cout << "Upper current bound of 'perm2': " << perm2.get_current_limit("upper") << "A" << endl;
    cout << "Number of coils in 'perm2': " << perm2.get_coil_count() << endl << endl;

    // Create a ElecMagnet (derived class) object
    ElecMagnet elec1("ElecMagnet 1", 170, 200, 850, 27);
    cout << elec1.get_classifier() << endl;
    cout << elec1.get_coil_count() << endl;

    return 0;
}

這段代碼的output是:

'perm1' age: 0
'perm2' age: 35 | 'perm2' name: PermMaget 2
Owner of 'perm2': Unspecified Staff
Upper current bound of 'perm2': 780A
Number of coils in 'perm2': 2

MAG-DP-
2

Process finished with exit code 0

如您所見,我希望“owner”、“classifier”和“coil_num”是用戶無法更改的私有成員。 這些也因所討論的 class 而異。

問題:

問題出在output的最后兩行。當派生class(ElecMa.net)繼承返回這些成員的公共函數時,它返回基類class的成員; 不是它自己的。 你可以看到這個,因為它返回 PermMa.net class 的“分類器”和“coil_num”。

有誰知道為什么派生的 class 會這樣? 它不應該訪問自己的私人成員而不是基地嗎?

私有成員只能被class或好友的成員函數訪問。 C++ 的行為與 Python 不同,后者根據當前指針this ( self ) 動態執行變量搜索。

發生這種情況是因為您仍在調用基類 class 的方法,它不知道派生類 class 的成員變量,因此不會使用它們。 要存檔您想要的內容,您需要覆蓋派生 class 中的get_classifier()以便通過ElecMa.net引用調用它會調用派生方法。 當通過PermMa.net -reference 在ElecMa.net -value 上調用它時,您可以選擇使方法成為virtual ,甚至可以調用派生版本。 (通常建議為 inheritance 設計virtual類。)

或者,根據您的用例,您可以編寫顯式構造函數來調用具有適當classifier值的(可能受保護的)基構造函數,而不是using基本構造函數。 這將為您完全節省派生的 class 中的其他成員變量。

Inheritance 使用“是”關系。 意思是,你應該能夠說一個孩子 object“是”基地 object。如果你不能這么說,你不應該使用 inheritance。

這對於構建派生 object 意味着它是一個組合,包含您的基礎 object,以及通過 inheritance 添加的任何額外位。

你調用了一個base object function,也就是說它會訪問base object的數據。 在派生的 class 中重復數據顯然是行不通的,是一種不好的做法。 如果您需要相同的數據,請使用它並且不要重復它。

為此,您可以讓派生的 class 構造函數始終在初始化部分首先調用基類 class 構造函數。 您根本不使用初始化部分,這會導致很多效率低下並最終導致錯誤。

隨機位:所有 class 數據都應該是私有的。 class 的protected:部分包含您希望孩子可以公開訪問但又不想完全公開的任何內容。 如果您不希望 getter 公開可用,他們可以在此處撥打 go。 我在這里放置了幾個專門為ElecMa.net而存在的構造函數。 using namespace std; 是不好的做法。

代碼:

#include <iostream>
#include <string>

class PermMagnet {
 public:
  PermMagnet() = default;
  PermMagnet(std::string c_name, int c_ac_rating, int c_dc_rating,
             int c_mass_kg, int c_age)
      : name(c_name),
        ac_rating(c_ac_rating),
        dc_rating(c_dc_rating),
        mass_kg(c_mass_kg),
        age(c_age) {}  // Use the initialization section

  std::string get_owner() const { return owner; }  // Mark getters as const

  std::string get_classifier() const { return classifier; }

  int get_coil_count() const { return coil_num; }

  std::string get_location() const { return location; }

  int get_age() const { return age; }

  std::string get_name() const { return name; }

 protected:
  PermMagnet(std::string owner, std::string classifier, int coilNum)
      : owner(owner), classifier(classifier), coil_num(coilNum) {}

  PermMagnet(std::string name, int ac_rating, int dc_rating, int mass_kg,
             int age, std::string owner, std::string classifier, int coilNum)
      : name(name),
        ac_rating(ac_rating),
        dc_rating(dc_rating),
        mass_kg(mass_kg),
        age(age),
        owner(owner),
        classifier(classifier),
        coil_num(coilNum) {}

 private:
  std::string owner = "Unspecified Staff";
  std::string classifier = "MAG-DP-";
  const int coil_num = 2;  // const probably unnecessary here, but left it
  std::string location = "facility hall";
  std::string name = "";
  int ac_rating = 0;
  int dc_rating = 0;
  int mass_kg = 0;
  int age = 0;
};

class ElecMagnet : public PermMagnet {
 public:
  ElecMagnet() : PermMagnet("Specified Staff", "MAG-QD-", 4) {}

  ElecMagnet(std::string name, int ac_rating, int dc_rating, int mass_kg,
             int age)
      : PermMagnet(name, ac_rating, dc_rating, mass_kg, age, "Specified Staff",
                   "MAG-QD-", 4) {}

  // NO NEED FOR REPETITIVE PRIVATE SECTION
};

int main() {
  // Create object using default constructor
  PermMagnet perm1;
  std::cout << "'perm1' age: " << perm1.get_age()
            << '\n';  // Prefer '\n' over std::endl

  // Create object using parameterised constructor
  PermMagnet perm2("PermMagnet 2", 380, 400, 1500, 35);
  std::cout << "'perm2' age: " << perm2.get_age()
            << " | 'perm2' name: " << perm2.get_name() << '\n';
  std::cout << "Owner of 'perm2': " << perm2.get_owner() << '\n';
  std::cout << "Number of coils in 'perm2': " << perm2.get_coil_count()
            << "\n\n";

  // Create a ElecMagnet (derived class) object
  ElecMagnet elec1("ElecMagnet 1", 170, 200, 850, 27);
  std::cout << elec1.get_classifier() << '\n';
  std::cout << elec1.get_coil_count() << '\n';

  return 0;
}

請注意, ElecMa.net class 目前只是幾個構造函數,而您的主要 function 的行為符合預期。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM