0

I am trying to port some classes from one big piece of C++ codes from another team to another piece of codes in our team.

Originally, inside the old program, there was a global variable "rawdata" which can be used by everyone. But when porting some classes, my senior told me to put "rawdata" into the major class, and use its constructor to initialize "rawdata". (I guess he wants as few global variables as possible)

However, my current situation is that, I don't know how to make other classes to access "rawdata" without passing an object. For example,

class majorpart() {
   int rawdata;
   majorpart(int input) {rawdata = input;};
}

class otherpart() {
   if(rawdate==0)          // Here we don't want an object of class majorpart
       do something;       // Is it possible for us to directly access rawdata?
}

I am kind of new to C++. Could anyone give me some suggestions? Thanks

  • I don't find this overly clear. You had a `global`, now you've put it into a `class`. Do others have access to that class? Could the variable be `public`? What about a singleton? – Tas Oct 16 '16 at 23:36
  • what sort of things are "A" and "B"? It's not clear from your post. If A is a class then it could not have had a global variable. – M.M Oct 16 '16 at 23:36
  • It looks like every *"piece of codes"* which needs access to `rawdata` should have a pointer to a (possibly singleton) `majorpart` instance. – zvone Oct 16 '16 at 23:39
  • Sorry about my confusing statements. "A" and "B" are just large project folders, they are not any particular classes. I will change "A" to "the old program from some other team" and "B" to "the new program in our team". –  Oct 16 '16 at 23:51
  • Does your `majorpart`-class do something that is needed as frequently as the `rawdata` field? – bash0r Oct 17 '16 at 00:01
  • @bash0r The "rawdata" as the member of "majorpart" class, will not be updated anymore after initialization. Then, "otherpart" classes just start using "rawdata". Originally, "rawdata" is a global variable, so it was convenient for every class to access it directly. Now I have to put it inside "majorpart" as a member, and I don't know how to enable other classes to access it. –  Oct 17 '16 at 00:11
  • @LightnessRacesinOrbit I am not a native speaker of English, so I apologize if I used the wrong words..... –  Oct 17 '16 at 00:13
  • I would create a singleton-class for the `rawdata` field. Then it's not in `majorpart`-class but accessible from everywhere. You can handle the initialization of the field in the new class for `rawdata` properly and even restrict write access so that manipulation of the field would cause a compilation error. – bash0r Oct 17 '16 at 00:13
  • @bash0r Thank you so much. I am not familiar with singleton-class, is it better/safer than a global variable? Does that mean "rawdata" inside this singleton-class can be accessible for "majorpart" and "otherpart" only? and any other irrelevant classes can not access "rawdata" at all? –  Oct 17 '16 at 00:21
  • Yes it actually is more safe as you can control how the field is initialized and accessed. You can't do that with a global variable. If you want it to be read-only, just define a getter-like function that allows access via `const T&` or `const T*`. Then `T` is `const` but you get a reference to it (e.g. no copying). I guess you're using something more complex than an `int`. You should make your `majorpart`-class the singleton-class if there is only one instance of it in your whole program. – bash0r Oct 17 '16 at 00:26
  • @bash0r Thanks so much. Could you please give me an example code based on my original post? (I will search for singleton-class as a student, but I will really appreciate it if you can show me how to start : ) ) –  Oct 17 '16 at 00:32
  • @bash0r Thanks for your response! I apologize for my earlier confusing question. In fact, I came across the same problem with the following link: http://stackoverflow.com/questions/17799134/c-singleton-undefined-reference-to –  Oct 17 '16 at 17:58

2 Answers2

0

Maybe you can treat rawdata as a static member, which means it's not associated with the objects of the class.

class X { static int n; }; // declaration (uses 'static')
int X::n = 1;              // definition (does not use 'static')
immiao
  • 102
  • 9
  • Thanks so much for your response. –  Oct 17 '16 at 00:15
  • Because there are many "otherpart" classes in my project, and some of them access "rawdata" based on some macro functions, it will be difficult for me to change every "rawdata" into "majorpart::rawdata". –  Oct 17 '16 at 00:26
  • @JimGreen You're going to have to change *something* if you move `rawdata` into a class. There are no two ways about this. If you can't manage the change, don't do it. – user207421 Oct 17 '16 at 00:46
  • @JimGreen I have to agree with EJB in that point. There is a reason why this kind of changes is called "refactoring". – bash0r Oct 17 '16 at 07:30
0

Based on your source code an example with a singleton-class:

class rawdata {
private:
  static int *_instance;
  rawdata() { }
public:
  static const int *instance() {
    if (_instance) return _instance;
    else return (_instance = new int(10));
  }
};

class majorpart {
  majorpart() { };
};

void doSomething() {

}

class otherpart {
  void someFunction() {
    if (rawdata::instance())          // Here we don't want an object of class majorpart
      doSomething();           // Is it possible for us to directly access rawdata?
  }
};

The idea is to wrap the rawdata field with a class to control how it is initialized, accessed, etc.

You mentioned in a comment to immiao's answer, that you would need to fiddle around with macros. You'd need to do this anyway. It doesn't matter if it is in majorpart as field, static field or in rawdata as a singleton-wrapper.

bash0r
  • 774
  • 6
  • 17
  • OK, now I get the point. So "singleton class" is a high-level program pattern or methodology, rather than some magical key words. –  Oct 17 '16 at 00:56
  • Thanks for your instructions, I really learnt a lot today. So basically, the your example code has a more sophisticate programming style, but it is similar to immiao's "static member" method. Is my understanding right? –  Oct 17 '16 at 01:00
  • @JimGreen - the advantage to a Singleton is you just instantiate it when needed. With a `static` member you have to pass an instance of the class to the function needing to use it, which may be many levels deep. – Tony Oct 17 '16 at 01:06
  • @JimGreen In Scala you actually have a keyword `object` (http://stackoverflow.com/questions/1755345/difference-between-object-and-class-in-scala) for the singleton-pattern. Every pattern can be abstracted as syntax. Though lack of syntax doesn't hold you back from programming in this particular style. It is similar to immiao's static member but not equal. You get more control over what can be done or (in your case) can not be done with the field. – bash0r Oct 17 '16 at 01:29
  • @bash0r Thanks. I followed your way to declare a singleton class called "rawdata". However, in order to get ride of "undefined reference to rawdata::_instance" compile error, I still need to define the static member somewhere, like this " int * rawdata::_instance = 0; " So it sill looks like a global variable, and I did not see the advantage here. (Sorry about my silly questions, but I just need to learn.) –  Oct 17 '16 at 04:28
  • @JimGreen sorry, my C++ is a bit rusty... I'll fix it as soon as I have my coffee. – bash0r Oct 17 '16 at 06:33
  • @JimGreen The snippet is correct. You need to access the field by using the `rawdata::instance()` function. You can't access `rawdata::_instance` from outside the `rawdata`-class. It would break encapsulation. You must initialize `rawdata::_instance` in the `rawdata::instance()` function like I did. You could hack that away with a `rawdata::initialize(const int *rawdata)` function that can initialize the field in a one way manner. But I would recommend you to handle initialization in `rawdata::instance()`. As Tony pointed out, you get lazy initialization by this pattern. – bash0r Oct 17 '16 at 07:09