簡體   English   中英

在c ++中訪問不同類中的類的成員

[英]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 Afriend 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對象,從而產生效果。

我找到了一些建議嘗試通過引用AA (B& b) : b(b) {;}的構造函數來傳遞類型B的對象A (B& b) : b(b) {;}但這也不起作用。

那不行。 當你這樣做時會發生什么,是使用引用傳遞的值初始化A::b ,為true。 但是引用只會導致沒有傳遞給正在構造函數的b附加副本 此引用不會在傳遞給構造函數的bA::b之間創建鏈接。 這是另一端,所以說。

順便說一句, A (B& b) : b(b) {;} c'tor參數名稱與成員名稱相同是一種不好的做法 讓它們以相似的方式命名是一個好主意,但仍然添加例如下划線: A (B& _b) : b(_b) {;}

如果要在第一個片段中獲得相同的結果,請返回對b引用 ,如下所示:

  B& get_b() { return b; }

但是,這是不可取的,因為您公開A類的私有成員只是為了允許A客戶端修改該成員的某個屬性。 更好地在A提供一個方法來設置A::bval屬性,而不提供對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.

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