I'm learning C++ and moving my project from C to C++. In the process, I stumbled on this problem: how to save/update variables that are in use in several classes? In C I used global variables, but it is not good for C++.
So, let's assume we have 4 classes:
class Main_Window
{
//...
void load_data_menu_selected();
}
class Data
{
//...
double *data;
}
class Load_Data
{
//...
double *get_filename_and_load();
}
class Calculate
{
//...
int do_calculation()
}
So, Main_Window is class for application's main window where it interacts with user input etc.
I want to do:
create an instance of class Data in the Main_Window
use Load_Data for loading data from file and store it in the Data
use Calculation class for doing something with read data in Data class
The question is: where I should create classes, to make Data class members available from other classes. Should I use Inheritance?
Start from observing what are possible relations between instances of two classes. Let us say a is an instance of class A and b is an instance of class B. If a uses b, class A can have as its member instance of class B (b), pointer to b (which is of type B*), or reference of b (which is of type B&). If only one method of class A uses b, you have again same three options: B, B* or B& can be method's arguments. Having B* and B& as class members suggests that a does not control b's lifetime so class A must have a method that sets these members through its parameters. The question of ownership (objects' lifetimes) has a big role in design of relationship between classes. Main relationships are briefly described in this article.
I think you only want to have a Main_Window class, and the rest should be members of that class.
class Main_Window
{
private:
DataObject windowData;
public:
void loadData(string fileName);
void calculate();
}
Inside the loadData and calculate methods, you will be able to access the same data with this->windowData . Sorry if my syntax is bad, my c++ is rusty
Typically, you would pass (const) Data& around as an argument. If do_calculation() needs a Data to work with, then it takes Data&. But I can't really be more specific or useful unless you post more of your design.
You need to know how to design in OO. Thinking in C is different from thinking in c++. You can that your classes have many methods. Well, that sound like a bad design.
I can recommend you to start with the SOLID principle.
Then start writing unit tests for your classes. TDD could help you improve your design even further.
It sounds like you should not use inheritance here. The main reason for saying so is that you have a number of classes (Window, Calculator, etc.) using or doing something to an entity (i.e. Data). Inheritance is used to denote an "is a" relationship (i.e. if A inherits from B, A "is a" B).
In this case, you use composition, which denotes a "has a" relationship. So each class takes a reference to an instance of Data, and acts upon that object.
Who owns the Data object? To share a single Data object, you might want to look into Boost shared_ptr, which allows multiple reference-counting pointers to share an object allocated with "new".
Related
Suppose, that I have an abstract base State class and at least two derived classes AnimalState and PlantState(also abstract). Also, I have many derived classes from AnimalState and PlantState.
class State{} // abstract
class AnimalState: public State{} // abstract
class PlantState: public State{} // abstract
//maybe few more of such classes here
class AnimalStateSpecific1: public AnimalState{}
class AnimalStateSpecific2: public AnimalState{}
... //many of them
class PlantStateSpecific1: public PlantState{}
class PlantStateSpecific2: public PlantState{}
... //many of them
Now suppose, that I use them in some kind of method that operates on base State pointers. Those pointers are replaced over time with other pointers to different class from the State hierarchy. It happens by some rule, specifically within the predefined state graph.
Now to the question part. In order to determine the next state, I need to know the previous one. But since I have only base State pointers, I can not efficiently tell what type of state I have, without doing dynamic_cast to every derived class in the hierarchy that is not good. I can have some enum with all kinds of states that I have, but I do not really like that because I do not want to mix information from two hierarchy branches, as it is really different. Also, I do not like different enums for every branch in the hierarchy such as AnimalStateEnum, PlantStateEnum etc.
What is the best solution for this problem? Maybe my design is not good from the start? I want to keep it as generic as possible and work only with base class objects, if possible.
Now to the question part. In order to determine the next state, I need to know the previous one.
Simplest solution based on limited information we have - object, which knows it's own state creates next state object:
class State{
public:
...
virtual std::unique_ptr<State> transform( some data ) = 0;
};
then you implement it in each derived from State class which can change it's state and knows where it can move to. What data you need to pass is not a simple question - it depends on your task and may have various options, but you need to define something that can be used by all derived classes, as signature is defined on the base class and shared on all derived ones.
What is the best solution for this problem? Maybe my design is not good from the start?
This question is not trivial and only can be answered having pretty deep knowledge on your task. If you are unsure - implement a prototype and check if solution fits your problem well. Unfortunately the only way to learn how to create a good design is your own experience (except trivial cases of course).
You could simply have a virtual method next() inside the state class hierarchy,
and then do something similar to the following example:
State *globalState = nullptr;
void foo(State *s)
{
globalState = s->next();
}
Where each derived class will implement next() to its own meaning:
PlantStateSpecific1 *AnimalStateSpecific1::next(){ return new PlantStateSpecific1; }
AnimalStateSpecific1 *PlantStateSpecific1::next(){ return new AnimalStateSpecific1; }
This is more OOP than having an enum / integer descriptor of the derived class.
What you can have is an integer inside the base state class that every class below it will set in its constructor. Then you can either use a sereis of constants, a list of possible states with the id corresponding to the state type index, or use an enumerator.
The id is more flexible as you can create state types with relative ease and add handling to them without too much difficulty, aswell as if you want to create a new state from the id type.
Just one of the ways iv done this before, but there are probably many others.
I give the following examples to illustrate my question:
class B;
class A
{
public:
class B *pB;
};
class B
{
public:
void perform(A &obj)
{
}
};
In the above two classes. class A has a pointer to class B. class B has a function that will work on class A object. Though it can compile, I was wondering whether this is not a good practice for designing two classes as they are intertwined. If this is bad design, do you have some ideas to avoid it? Thanks.
Having two concrete classes rely directly on one another can get you into trouble.
It is often better to "program to an interface".
There is a long discussion here under the title "Program to an interface, not an implementation", which draws out why decoupling matters
In your example, void perform(A &obj) could instead take an abstract base class that A derives from. It might be worth having an interface that A uses in it's member variable too, but there' no suggested usage in your example to go on.
Why is this "better"? For starters, it will make you think about encapulsation - and what specifically the interface should be exposing.
It will also allow you to use different conrete instantions of the class, say for testing purposes.
If you use an interface, you can change the conrete classes separately... there are many advantages.
Problem:
I have totally separate software managers (software entities), for example CCarManager, CTruckManager etc.. At some point I am creating new objects for example CCar. CCar must have relationships with various separate managers, for example, with CResourceManager, CTruckManager. What is the best way to link CCar with these managers?
Solutions:
Have global software managers (Singleton or extern in header file)
[Don't like globals]
Use one global point and pass it to other obects e.g CCar(CApplication), CApplication->TrukManager(), CApplication->CarManager()...
[Doesn't seem nice, but can pass one pointer]
Pass to CCar(CCarManager *pCarManager, CTruckManager *pTruckManager....)
[Hard to extend]
Use Observer pattern e.g. CCar.Attach(CCarManager), CCar.Attach(CTruckManager);
[Easy to extend, but main focus become for dealing method calls, what parts are responsible for what etc., also lot of check's]
Factory.
class CCarFactory(CCarManager *pMngr)
{
CCar *CreateCar()
{
return CCar(m_pCarManager);
}
}
what are the other ways?
You can pass a reference to CResourceManager, CTruckManager, etc. in CCar's constructor.
CCar(const CResourceManager& resourceMgr, const CTruckManager& truckMgr):
_resourceMgr(resourceMgr), _truckMgr(truckMgr) {
//relevant construtor code here
}
This way it's easy to test with mock implementations as well. It's hard to say without knowing what the 'Manager classes do.
IMHO, classes whose names end in 'Manager' are often either poorly named (which I've done more times than I can count), or poorly designed.
If the only reason you won't use the Singleton pattern is because you don't like it, I think you might want to reconsider your approach.
Singletons are a perfect pattern for what you're trying to acheive here. You have management classes that should only have one instance and require access from many other classes.
Its hard to say without some more specifications... If CCar requires special access to the manager methods (like internal variables/methods) or vice-versa, you can declare in CCar managers as friend, or CCar as friend in those manager classes.
simple example, mind the poor member names
class CCar
{
int I;
public:
friend class CManager;
CCar(int i): I(i) {}
};
class CManager
{
int D;
public:
CManager(int i, CCar& car): D(i)
{
car.I = 5; // modify CCar instance internal member
}
};
or vice versa if its the other way around.
If a CCar instance can have multiple CCarManagers, you could set up an array of pointers to 'link' those managers to an instance of CCar. Rather than having 3 different pManager arrays, having a Manager base class, and subclassing those managers to it, will let you store all references to managers in a single array.
class Manager // etc...
class CResourceManager : public Manager
// in CCar
std::vector<Manager*> _mgrs;
// or if heap allocated
std::vector<std::shared_ptr<Manager>> _mgrs; // assuming multiple CCars can reference same manager instance
Another method could be to have a struct/class that can hold all manager references for a particular instance.
struct MgrRefs
{
std::vector<CCarManager*> _pCarMgrs;
std::vector<CResourceManager*> _pResMgrs;
// etc....
};
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I have taken several classes now in C++ and a little bit of python. And a common thing that keeps coming up is my failure to really understand whats going on when you are creating a class. I was wondering if someone could either explain the specifics as far as classes in C++ are concerned or least point me to websites that go into great detail. I know the declaration but as far as what is going on with accessors, methods, constructors and destructors and even if you'd like to go as far as define when and why would the best time to use a class. I just need overall clarification. Thanks!
In programming, you have data and functions that manipulate that data. A structure (struct) allows you to group related pieces of data into one logical object.
A class allows you to group data and functions together as a single unit. Thus, instead of saying matrix_add(m1, m2), you can say m1.add(m2). The data and functions can be private (only accessible to the class), protected (accessible to the class and its children) or public (accessible to anyone). This is called encapsulation: typically, the data is private and is accessible via a set of public functions. In C++, a struct defaults to public scope and a class to private scope, but are otherwise identical.
An accessor is the name of a function that typically provides acccess to the private data of a class. These can be getters that return (or get) the data, or setters that modify (or set) the data. Typically, these methods check the input for validity to ensure internal constraints hold. Note that an accessor may not directly return private data, but derived properties; that is, size and empty on C++ containers (vector, list, ...) could be thought of as accessors even though these could be computed values.
A constructor is a special function that allows the class to initialize the data to sane values, or allow the user to create a new object of the class with potentially different data. For example, a rectangle class could be constructed from another rectangle, a point and size, a set of top/left/bottom/right values or could be empty. In C++, the constructor has the same name as the class; in python this is called __init__.
A default constructor is a constructor that takes no parameters and initializes the class to its default state (e.g. an identity matrix for a matrix class).
A copy constructor is a constructor that takes another object of the class type and creates a copy of it. This allows allocated memory to be handled properly (e.g. for string and vector classes). With a simple data structure the objects are copied by value, so the two objects would reference the same memory.
A destructor is a special function that allows the class to perform cleanup. This could be things like deleting any allocated memory, releasing locks on mutexes or closing open file handles. In C++, a destructor has the same name as the class but with a ~ in front of it, e.g. for a matrix class the destructor would be ~matrix.
A method is just a function that is a part of a class. Each method takes the class object being operated on as the first parameter. When declaring methods, C++ does this internally for you (providing an implicit this argument) while python requires you to provide the parameter explicitly.
In C++, an operator is a special function that is used to implement e.g. +, -, * and /. This allows you to create classes that can be used like built in types (esp. for mathematical classes like vectors, matrices, complex and rational numbers).
A class (the "derived" class) can inherit from another class (the "base" class). Here, the derived class is a child of the base class and can access any protected data or methods. This is called inheritance. These form a class heirarchy.
A class can be constructed to have virtual methods that can be overriden by derived classes. This is called polymorphism.
You can declare virtual methods that do not provide any implementation. These methods are called pure virtual methods and the classes that provide them are known as abstract base classes. Here, the derived class needs to implement these methods, while with non-pure virtual methods the derived class does not need to implement the method.
A class that only has pure virtual methods (no other methods) is effectively an interface class. C++ does not have any special notation for this, whereas other languages do.
Interfaces are typically used to interact between two or more different systems. For example, a music player could provide a plugin architecture that allows plugins to extend the supported audio formats it can handle. Here, the interface(s) provide the contract between the player and plugin.
Think of objects as "smart" structures which not just contain data but also the code to manipulate that data. Think of classes as type definitions for these "smart" structures.
Creating a class instance is just like creating a variable of a structure type. Calling a member function of a class is just like calling a normal function, and passing the structure to it as a parameter with the name "this".
When you understood this, you already understand most about what object-oriented programming is all about.
By the way: Do you know what's the difference between the keywords struct and class in C++? In a struct, all members are public by default and in a class all members are private by default. That's it. Otherwise structs and classes are the same thing. When you explicitely declare all members as private, public or protected, you can switch them out and the program will compile and work just like before.
And a common thing that keeps coming up is my failure to really understand whats going on when you are creating a class.
I'm answering this part as others have answered the second part, code below is java however, looking at the code kindly give importance to class concept than Java constructs.
Well, before jumping into the CLASS thing in the programming world. Lets take a look a the real world. If we look around us we see many elements [rocks, animals, humans, plants etc] in our living echo system. Careful observation finds that, they have some common features that can be grouped together [Life, Organs, Color etc] , lets call this common grouping by a technical name called "CLASS".
In order to understand, classes in programming world one should understand why there is such a construct called class. Main fact is the it is part of a programming paradigm called Object Oriented Programming, where, programmers try to map real world objects say Vehicles, Banks, etc into programming models called Objects. In order to create these object, we have to create a construct that can actually describe those objects. Such a construct is called a class.
Below explanations goes beyond just Classes for completeness.
Lets look at a technical example Circle, Rectangle, Square, Hexagon, looking at them we find that they belong to a common CLASS called SHAPE.
Don't get carried away by details [extends, #Override etc] in the example below. It explains simple concept of classing how it is exploited to make new classes. Once a class is created, it is just a skeleton ie it is not allocated any memory for a real use. In order to make a class useful, we create its objects. So objects are 'elements' with different states for same class.
Say for circle objects, obj1, obj2, each object have different radius.
class Shape {
String name;
int color;
public Shape(String name, int color) {
this.name = name;
this.color = color;
}
String getName() {
return name;
}
int getColor() {
return color;
}
double getArea() {
return 0;
}
double getPerimeter() {
return 0;
}
}
class Rectangle extends Shape {
int l, b;
public Rectangle(int l, int b, int h, int color) {
super("Rectangle", color);
this.l = l;
this.b = b;
}
/* Overloading */
#Override
double getArea() {
return l*b;
}
/* Overloading */
#Override
double getPerimeter() {
return (2*l + 2*b);
}
}
class Circle extends Shape {
int r;
public Circle(int r, int color) {
super("Circle", color);
this.r = r;
}
dobule getArea() {
return (PI * (r*r));
}
double getPerimeter() {
return (2*PI*r);
}
}
I have a class A consisting of a bunch of internal data structures (e.g. m_data) and a few objects (e.g. ClassB):
class A
{
public:
...
private:
int m_data[255];
ClassB B[5];
}
What's the best way for B to access m_data? I don't want to pass m_data into B's function..
// updated:
Many thanks for the responses. Let me provide more contextual info.
I am working on an AI project, where I got some data (e.g. m_data[i]) at each time step. The class A needs to buffer these information (m_data) and uses a list of B's (example updated) to make inference. Class B itself is actually a base class, where different children derive from it for different purpose so I guess in this context, making B a subclass of A might not be clean (?)..
friend class ClassB;
Put this line anywhere in A's declaration if you want ClassB to access all of A's protected and private members.
One of:
Make ClassB a friend of A
Make A a sub-class of ClassB and make m_data protected rather than private
[In response to Mark B's comment]
If ever you feel the need to resort to a friend relationship, the design should be reconsidered - it may not be appropriate. Sub-classing may or may not make sense; you have to ask yourself "Is class A and kind of class ClassB?" If the question makes no sense intuitively, or the answer is just no, then it may be an inappropriate solution.
Ideally, you don't allow external access the data structure at all. You should rethink your approach, considering more the question "What are the functional requirements / use cases needed for ClassB to access instances of A" rather than offloading the management of the internal members to methods not managed within class A. You will find that restricting management of internal members to the class owning those members will yield cleaner code which is more easily debugged.
However, if for some reason this is not practical for your situation there are a couple possibilities that come to mind:
You can provide simple get/set accessor methods which, depending upon
your requirements, can be used to access either a copy of or a
reference to m_data. This has the disadvantage of allowing everybody
access, but does so only through well defined interfaces (which can
be monitored as needed).
ggPeti mentions use of friend, which may work for you, but it gives ClassB access to all of the internals of A.
A getData() function that returns m_data.
Use setData() to change the value.
So in the function in class B you would create a pointer to the class type A variable that you created. Lets just call this pointer 'p'.
Just do p->getData(), p.getData() may be the answer. I think they do the same thing but c++ uses the '->' and some other languages use the '.'. Don't quote me on that one though.
Good luck, sir. Hope I helped ya.
What's the best way for B to access m_data?
Depends on the use.
This is how would I do it :
class ClassB
{
// ...
void foo( A &a )
{
// use a's data
}
};
class A
{
//...
int m_data[255];
ClassB & B;
};
Depending on the implementation, maybe ClassB is not needed at all. Maybe it's methods can be converted to functions.