0

This may be a stupid question, but what is the best way to program 2 classes that share a set of variables?

  1. Class A and Class B both need access to int x and int y.
  2. If class A changes x or y, the changes should be reflected in class B

My thoughts: Class A and B can inherit Class C (which contains the variables x,y) - But this would create an instance of c for both A,B. - I only need one instance of x and y

Maybe I need friend class, or static variables?

einpoklum
  • 118,144
  • 57
  • 340
  • 684

2 Answers2

3

First of all - it depends. You've not told us the whole story. But you've already made some assumptions I want to discourage you from making.

The fact that A and B share some common data does not mean that they are inherently the same. A person may have a travel destination and a conference may have a venue, but that doesn't mean they need to be subclasses of the same thing.

So it could very well be the case that the following is what you should use:

struct C { int x; int y; };

class A { 
    C& foo;
    int bar;
    A(C& some_c) : foo(some_c) { }
    // ... etc. ...
};

class B { 
    C& baz;
    int qux;
    A(C& some_c) : baz(some_c) { }
    // ... etc. ...
};

with no inheritance, no friend classes, no static variables - none of that stuff. And it may be the case that inheritance is appropriate; again, it depends.

Note: The example I gave does not address potential divergence in scope/lifetime of A, B and C variables. If there is such divergence, it may make sense to create all of these objects on the heap and have A and B hold std::shared_ptr's to a C.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • This example will cause crashes. If (when) someone deallocates an instance of `C` before an instance of `A` or `B` is done using it, it will do unspeakable things. People still (for some reason) do manual memory management. Using a `std::shared_ptr` instead of `C&` would give you the same result, but safer. – Clearer Apr 06 '18 at 14:54
  • @Clearer, not it won't. There is no need to use `shared_ptr` when it is not needed. In this case, depending on the usage, it might be needed or not needed, and a wide suggestion you are making is not warranted. – SergeyA Apr 06 '18 at 15:00
  • @Clearer: Indeed, no it won't, but you make a valid point in that you have to be careful about scope/lifetime. See edit. – einpoklum Apr 06 '18 at 15:04
  • It certainly will cause problems. Maybe not a crash immediately, but you're definitely going to get into problems. Your note justifies an upvote. – Clearer Apr 06 '18 at 15:10
  • @Clearer I suggest, you become less imperative. Nobody is 'definitely' going to get into problems. Using dynamic allocation when one is not needed is a serious pessimization. I suggest you teach less and learn more. – SergeyA Apr 06 '18 at 15:15
  • @Clearer: `void f(int x) { C c {x, 123}; A a(a); B b(c); do_stuff(a,b,c); }` No problem whatsoever. – einpoklum Apr 06 '18 at 18:37
  • `C * c = new C(); A a(*c); a.c.x = 1; delete c; c = new C(); A b(*c); std::cout << b.c.x;` Should print out 1, even though you haven't touched the second `C`. – Clearer Apr 06 '18 at 18:39
  • @Clearer: It is now [officially discouraged to engage in direct allocation and de-allocation of memory](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rr-newdelete). So - you should not be writing this kind of code. Plus - there seems to be no reason for you to create C on the heap rather than the stack, and thus no reason to use pointers. – einpoklum Apr 06 '18 at 18:44
  • @einpoklum I've always encouraged people to stop using new/delete long before it became official policy. I consider new/delete to be bugs. People still think global variables are a good option. Experience tells me that people *will* manage memory on their own and they *will* get it wrong. – Clearer Apr 06 '18 at 21:03
  • @Clearer: Then even for that reason I would rather not nudge them into using pointers :-) Also, if you can convince someone to use smart pointers, you can probably convince them to use _no_ pointers... – einpoklum Apr 06 '18 at 22:32
  • @einpoklum In my experience no. People think you must use Pointers! (capital P, exclamation mark) because C++ starts with a C! (capital C, exclamation mark). In my experience, getting people to use "smart pointers" is easier because it still contains the word pointer. Anyway, my point wasn't that the solution should use pointers, but to point out (some punt intended) a potential problem for people who aren't concious of lifetimes of variables and scopes. – Clearer Apr 06 '18 at 22:35
-1

Use a base class with static variables:

#include <iostream>
struct C
{
    static int x;
    static int y;
};

struct A : C
{

};

struct B : C
{

};

int C::x = 0;
int C::y = 0;

int main()
{
    A a;
    a.x = 1;
    a.y = 2;
    B b;
    std::cout << b.x << b.y << '\n';
}

If you find yourself in a situation where you think you need to do this, please reconsider your design.

Clearer
  • 2,166
  • 23
  • 38
  • Just use global variables, no need to make a class for them. – SergeyA Apr 06 '18 at 14:35
  • 1
    Disregard @SergeyA's "advice". – Clearer Apr 06 '18 at 14:36
  • 4
    Can you be any less constructive with your argument? – SergeyA Apr 06 '18 at 14:39
  • 1
    @SergeyA why global variables? What's wrong with static class members? – Jabberwocky Apr 06 '18 at 14:40
  • 1
    Global variables pollutes your entire namespace, while static member variables, at least, only pollutes the namespace of your classes. – Clearer Apr 06 '18 at 14:40
  • 1
    At least you can use namespace, class is not intended for this use. – llllllllll Apr 06 '18 at 14:41
  • @MichaelWalz they serve no purpose in this scenario (they could in other cases, but not now), so no real need for them. – SergeyA Apr 06 '18 at 14:43
  • 1
    @liliscent yep, agreed. Namespaces are much more suited for this. I also very much disagree with last sentence, `If you find yourself in a situation where you think you need to do this, please reconsider your design.` As a general statement, it makes 0 sense. – SergeyA Apr 06 '18 at 14:43
  • @liliscent If you want to limit access to the variables to the classes and it's descendants, namespaces are not an option. – Clearer Apr 06 '18 at 14:43
  • 1
    @Clearer, first, you are not limiting access in your example. Second, there is no goal of limiting access in the original question either. You are inventing things now. – SergeyA Apr 06 '18 at 14:45
  • @SergeyA No, in my example, there is no limit; it should be fairly easy for anyone to figure out how to add any limitation they want if they know 2 bits about how C++ works. The goal of the question was to provide access to a set of shared variables between two classes. The OP suggested using a base class, which indicates to me that there was a desire to make the variables tied to the classes. You disagree with me and that's fine. You seem to want to perpetuate the worst crime in all of software development -- please do that elsewhere. – Clearer Apr 06 '18 at 14:49
  • Pray to tell me, what is this 'worst crime of all software development' you are so sure about? – SergeyA Apr 06 '18 at 14:58
  • @SergeyA: To be honest, I also think you shouldn't suggest global variables here. – einpoklum Apr 06 '18 at 23:04
  • @einpoklum we can always have an intelligent discussion on pros and cons of technical solutions. If you think it is not warranted, you can present your arguments. – SergeyA Apr 09 '18 at 13:21
  • @SergeyA: The [general argument](https://stackoverflow.com/questions/484635/are-global-variables-bad) against global variables, combined with the fact that you don't actually need them here. – einpoklum Apr 09 '18 at 13:49
  • @einpoklum I am not sure what OP needs (neither OP is, in my honest opinion). It is not clear if OP needs to modify those values from outside of classes or not. – SergeyA Apr 09 '18 at 14:01