[英]Access members of a class within a different class in c++
我試圖理解使用c ++的面向對象編程。 以下是一個最小的例子,結果不是我天真的期望:
#include <iostream>
class B {
public:
B (int val) : val(val) {;}
int get_val() { return val; }
int set_val(int a) { val = a; }
private:
int val;
};
class A {
public:
A (B b) : b(b) {;}
B get_b() { return b; }
private:
B b;
};
int main(){
B b_main(5);
std::cout << b_main.get_val() << std::endl; // Prints 5, which makes sense
A a_main(b_main);
std::cout << a_main.get_b().get_val() << std::endl; // Prints 5, which makes sense
a_main.get_b().set_val(2);
std::cout << a_main.get_b().get_val() << std::endl; // Why does this not print 2?
return 0;
}
最后一個cout聲明對我沒有意義。 在倒數第二行,我將對象的值設置為2,那為什么不打印2? 看看Stack Exchange上的一些類似問題,我找到了一些建議,讓A和B成為彼此的朋友。 我嘗試在friend class A
類中添加friend class A
在friend class A
類中添加friend class A
friend class B
,但這不起作用。 根據我的理解,添加友元語句應該是不必要的,因為我在類A中有get_b()
方法。我發現一些建議嘗試通過引用A: A (B& b) : b(b) {;}
的構造函數來傳遞類型B的對象A (B& b) : b(b) {;}
但這也不起作用。
任何人都可以向我解釋為什么程序沒有產生預期的結果,以及如何獲得所需的結果(也就是說,最后一個cout語句打印2)?
注意:我還嘗試了以下內容。 我使A類的私有變量b成為公共的:
#include <iostream>
class B {
public:
B (int val) : val(val) {;}
int get_val() { return val; }
int set_val(int a) { val = a; }
private:
int val;
};
class A {
public:
A (B b) : b(b) {;}
B b; // This is now public
//B get_b() { return b; } // This is no longer needed
private:
};
int main(){
B bmain(5);
std::cout << bmain.get_val() << std::endl;
A amain(bmain);
std::cout << amain.b.get_val() << std::endl;
amain.b.set_val(2);
std::cout << amain.b.get_val() << std::endl; // Works!
return 0;
}
現在我獲得了理想的結果。 這是代碼應該如何實現而不是第一個代碼片段? 我想在第一個代碼片段中有一個get_b()
方法,但如果這不是正確的方法,請告訴我。
在倒數第二行,我將對象的值設置為2,那為什么不打印2?
因為您使用get_b()
方法返回a_main
B
對象的副本 。 會發生什么是復制a_main
中的b
變量,即創建與b
成員相同的另一個B
類對象,並返回給調用者。 然后,修改新的B
對象。 但它與a_main
的原始b
沒有關聯。 這與可見性和成員訪問幾乎沒有關系。
但是,在第二個示例中,您在a_main
公開b
成員並直接對該對象進行操作而不復制它,從而獲得成功結果。 public
修飾符更改的是它允許您直接訪問b
對象,從而產生效果。
我找到了一些建議嘗試通過引用
A
:A (B& b) : b(b) {;}
的構造函數來傳遞類型B的對象A (B& b) : b(b) {;}
但這也不起作用。
那不行。 當你這樣做時會發生什么,是使用引用傳遞的值初始化A::b
,為true。 但是引用只會導致沒有傳遞給正在構造函數的b
附加副本 。 此引用不會在傳遞給構造函數的b
和A::b
之間創建鏈接。 這是另一端,所以說。
順便說一句, A (B& b) : b(b) {;}
c'tor參數名稱與成員名稱相同是一種不好的做法 。 讓它們以相似的方式命名是一個好主意,但仍然添加例如下划線: A (B& _b) : b(_b) {;}
如果要在第一個片段中獲得相同的結果,請返回對b
的引用 ,如下所示:
B& get_b() { return b; }
但是,這是不可取的,因為您公開A
類的私有成員只是為了允許A
客戶端修改該成員的某個屬性。 更好地在A
提供一個方法來設置A::b
的val
屬性,而不提供對A::b
完全訪問權限。
絕對看到這一點: 通過引用傳遞與傳遞值之間有什么區別?
也許這樣: Java和C ++按值傳遞並通過引用傳遞
因為我覺得你是來自Java並且期望默認使用C ++中的pass-by-reference。
get_b返回私有變量b的副本,而不是實際變量。 如果您希望能夠訪問它,則需要返回對b的引用,以便可以操作返回的值。 你的get_b定義應如下所示:
B& get_b() { return b; }
如果那是你期望的。 但是,這通常不是理想的解決方案。 如果您要主動更改b的值,則應編寫set_b函數來操作變量。 如果你真的正在使用變量,讀取和寫入值,你應該公開它以便快速訪問。
只是為了完整起見,您可以將此問題解決為C編程問題,而不是在C ++編程中使用所有花哨的引用。 當您從a_main獲取b_main時,返回的對象不會占用相同的內存地址。
#include <iostream>
class B {
public:
B (int val) : val(val) {;}
int get_val() { return val; }
int set_val(int a) { val = a; }
private:
int val;
};
class A {
public:
A (B b) : b(b) {;}
B get_b() { return b; }
private:
B b;
};
int main(){
B b_main(5);
B* addrb = &b_main;
std::cout << b_main.get_val() << std::endl; // Prints 5, which makes sense
std::cout<<"Address of b_main: "<<addrb<<std::endl;
A a_main(b_main);
B bt = a_main.get_b();
addrb = &(bt);
std::cout << a_main.get_b().get_val() << std::endl; // Prints 5, which makes sense
std::cout<<"Address of a_main.get_b(): "<<addrb<<std::endl;
a_main.get_b().set_val(2);
std::cout << a_main.get_b().get_val() << std::endl; // Why does this not print 2?
return 0;
}
注意新cout語句的地址差異。 解決這個問題的一種方法是返回指針而不是b本身。 即
#include <iostream>
class B {
public:
B (int val) : val(val) {;}
int get_val() { return val; }
int set_val(int a) { val = a; }
private:
int val;
};
class A {
public:
A (B b) : b(b) {;}
B* get_b() { return &b; }
private:
B b;
};
int main(){
B b_main(5);
//B* addrb = &b_main;
std::cout << b_main.get_val() << std::endl; // Prints 5, which makes sense
//std::cout<<"Address of b_main: "<<addrb<<std::endl;
A a_main(b_main);
//B bt = a_main.get_b();
//addrb = &(bt);
std::cout << a_main.get_b()->get_val() << std::endl; // Prints 5, which makes sense
//std::cout<<"Address of a_main.get_b(): "<<addrb<<std::endl;
a_main.get_b()->set_val(2);
std::cout << a_main.get_b()->get_val() << std::endl; // Why does this not print 2?
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.