简体   繁体   English

在c ++中访问不同类中的类的成员

[英]Access members of a class within a different class in c++

I am trying to understand object oriented programming using c++. 我试图理解使用c ++的面向对象编程。 The following is a minimal example for which the result is not what I naively expect: 以下是一个最小的例子,结果不是我天真的期望:

#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;
}

The last cout statement does not make sense to me. 最后一个cout声明对我没有意义。 In the second to last line, I set the value of the object to be 2, so why does this not print 2? 在倒数第二行,我将对象的值设置为2,那为什么不打印2? Looking at some similar questions on Stack Exchange, I found some suggestions to make A and B be friends of each other. 看看Stack Exchange上的一些类似问题,我找到了一些建议,让A和B成为彼此的朋友。 I tried adding friend class A in class B and friend class B in class A, but this did not work. 我尝试在friend class A类中添加friend class Afriend class A类中添加friend class A friend class B ,但这不起作用。 In my understanding, adding the friend statements should be unnecessary since I have the get_b() method in class A. I found some suggestions to try passing the object of type B in by reference to the constructor of A: A (B& b) : b(b) {;} but this did not work either. 根据我的理解,添加友元语句应该是不必要的,因为我在类A中有get_b()方法。我发现一些建议尝试通过引用A: A (B& b) : b(b) {;}的构造函数来传递类型B的对象A (B& b) : b(b) {;}但这也不起作用。

Can anyone explain to me why the program is not producing the intended result and also how to obtain the desired result (that is, the last cout statement prints 2)? 任何人都可以向我解释为什么程序没有产生预期的结果,以及如何获得所需的结果(也就是说,最后一个cout语句打印2)?

Note: I also experimented with the following. 注意:我还尝试了以下内容。 I made the private variable b of class A be public: 我使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;
}

And now I obtain the desired result. 现在我获得了理想的结果。 Is this how the code should be implemented as opposed to the first code snippet? 这是代码应该如何实现而不是第一个代码片段? I would like to have a get_b() method as in the first code snippet, but if this is not the correct way of going about this, please let me know. 我想在第一个代码片段中有一个get_b()方法,但如果这不是正确的方法,请告诉我。

In the second to last line, I set the value of the object to be 2, so why does this not print 2? 在倒数第二行,我将对象的值设置为2,那为什么不打印2?

Because you return a copy of the B object in a_main with the get_b() method. 因为您使用get_b()方法返回a_main B对象的副本 What happens is that the b variable in a_main is copied, ie another object of class B , identical to the b member, is created, and returned to the caller. 会发生什么是复制a_main中的b变量,即创建与b成员相同的另一个B类对象,并返回给调用者。 Then, that new B object is modified. 然后,修改新的B对象。 But it has no connection to the original b in a_main . 但它与a_main的原始b没有关联。 This has little to do with visibility and member access. 这与可见性和成员访问几乎没有关系。

However, in the second example, you expose the b member in a_main and directly operate on that object without making a copy of it, thus the successful result. 但是,在第二个示例中,您在a_main公开b成员并直接对该对象进行操作而不复制它,从而获得成功结果。 What the public modifier changes is that it allows you to access the b object directly, hence the effect. public修饰符更改的是它允许您直接访问b对象,从而产生效果。

I found some suggestions to try passing the object of type B in by reference to the constructor of A : A (B& b) : b(b) {;} but this did not work either. 我找到了一些建议尝试通过引用AA (B& b) : b(b) {;}的构造函数来传递类型B的对象A (B& b) : b(b) {;}但这也不起作用。

That isn't going to work. 那不行。 What happens when you do so, is that the A::b is initialized using the value that is passed by reference, true. 当你这样做时会发生什么,是使用引用传递的值初始化A::b ,为true。 But the reference only leads to no additional copy of b passed to the constructor being made . 但是引用只会导致没有传递给正在构造函数的b附加副本 This reference does not create a link between the b passed to the constructor and A::b . 此引用不会在传递给构造函数的bA::b之间创建链接。 It's on the other end, so to say. 这是另一端,所以说。

By the way, A (B& b) : b(b) {;} that the c'tor parameter name is identical to the member name is a bad practice . 顺便说一句, A (B& b) : b(b) {;} c'tor参数名称与成员名称相同是一种不好的做法 It's a good idea to have them named similarly, but still, add eg an underscore: A (B& _b) : b(_b) {;} 让它们以相似的方式命名是一个好主意,但仍然添加例如下划线: A (B& _b) : b(_b) {;}

If you want to achieve the same result in the first snippet, return a reference to b like so: 如果要在第一个片段中获得相同的结果,请返回对b引用 ,如下所示:

  B& get_b() { return b; }

Still, this is undesirable, because you expose a private member of class A just to allow clients of A to modify a certain property of that member. 但是,这是不可取的,因为您公开A类的私有成员只是为了允许A客户端修改该成员的某个属性。 Better provide a method in A to set the val property of A::b without giving full access to A::b . 更好地在A提供一个方法来设置A::bval属性,而不提供对A::b完全访问权限。

Definitely see this: What's the difference between passing by reference vs. passing by value? 绝对看到这一点: 通过引用传递与传递值之间有什么区别?

and maybe this: Java and C++ pass by value and pass by reference 也许这样: Java和C ++按值传递并通过引用传递

because I have a feel that you're coming from Java and expect pass-by-reference in C++ by default. 因为我觉得你是来自Java并且期望默认使用C ++中的pass-by-reference。

get_b returns a copy of your private variable b, not the actual variable. get_b返回私有变量b的副本,而不是实际变量。 If you want to be able to access it, you need to return a reference to b so that the returned value can be manipulated. 如果您希望能够访问它,则需要返回对b的引用,以便可以操作返回的值。 Your get_b definition should look like this: 你的get_b定义应如下所示:

B& get_b() { return b; }

if that is what you expect to do. 如果那是你期望的。 However, this is not usually a desirable solution. 但是,这通常不是理想的解决方案。 If you are going to be actively changing the value of b you should write a set_b function to manipulate the variable. 如果您要主动更改b的值,则应编写set_b函数来操作变量。 And if you are really working with the variable a lot, reading and writing values to it, you should keep it public for fast access. 如果你真的正在使用变量,读取和写入值,你应该公开它以便快速访问。

Just for the sake of completeness, you can solve this problem as a C programing problem rather than using all the fancy references in C++ programing. 只是为了完整起见,您可以将此问题解决为C编程问题,而不是在C ++编程中使用所有花哨的引用。 When you get b_main from a_main, the returned object does not occupy the same memory address. 当您从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;

}

Notice the difference in address of the new cout statements. 注意新cout语句的地址差异。 One way to fix this is to return pointers rather than b itself. 解决这个问题的一种方法是返回指针而不是b本身。 ie

#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