[英]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.