I want to learn how to use class object within class, especially how to pass an arguments between the objects. I'm trying to create an example object Calc which should provide two methods Calc.sum and Calc.sub. It should use another object Plus as a math engine. The Plus.add function compile and works well. But I don't know how to initiate multiple instance of plus in the calc. The code:
class Plus{ // This class works well
public:
Plus(int); // Structure
int add(int); // Public method (function)
int myVar; // Public property. Just to hold a value.
private:
int _init; // Class-level private variable
};
Plus::Plus(int init){ // Constructor
_init = init;
}
int Plus::add(int p){ // Method add
return _init + p;
}
/***************************************************************************/
class Calc{
public:
Calc(int); // Structure
int sum(int); // Method sum
int sub(int); // Method sub
int myVar; // Public property
private:
Plus positive(int); // Class-level private object definition ?
Plus negative(int); // This is probably wrong ??
};
Calc::Calc(int init){ // Constructor (also wrong...)
Plus positive(init); // Create object "positive" and pass the initial value
Plus negative(-init); // Create object "negative" and pass the initial value
}
int Calc::sum(int n){
return positive.add(n);
}
int Calc::sub(int n){
return negative.add(n);
}
/***************************************************************************/
Plus two(2); // Create class object two
Calc five(5); // Create class object five
void setup(){
Serial.begin(115200);
Serial.print("two.add(3) = ");
Serial.println(two.add(3)); // Calling instance of class Plus
two.myVar = 100;
Serial.println(two.myVar);
Serial.print("five.sum(3) = ");
Serial.println(five.sum(3)); // Calling instance of class Calc
Serial.print("five.sub(3) = ");
Serial.println(five.sub(3)); // Calling instance of class Calc
}
void loop(){}
My example is inspired by this article: http://arduinoetcetera.blogspot.cz/2011/01/classes-within-classes-initialiser.html but the code there is for one instance only
1) How to declare multiple instances of Plus within Calc
2) Is the terminology (comments) right?
Your problem lies here
Calc::Calc(int init){ // Constructor (also wrong...)
Plus positive(init); // Create object "positive" and pass the initial value
Plus negative(-init); // Create object "negative" and pass the initial value
}
By doing this, you're creating local variables with the same name as your members: it has no effect.
Should be
Calc::Calc(int init): positive(init),negative(-init)
{
}
That way you initialize your members even if your members don't have a default constructor.
Oh and that is also wrong in definition of Calc
Plus positive(int); // Class-level private object definition ?
Plus negative(int); // This is probably wrong ??
replace by
Plus positive; // Class-level private object definition
Plus negative;
Related
I have two classes Instructor and Game.
Instructor.h
class Instructor
{
int instrID;
public:
Instructor();
void showGameStatus();
int createGame();
vector<int> createGames(int numberOfGames);
};
Game.h:
class Game {
private:
int gID;
int instrID;
int pFactID;
public:
Game() { // default constructor
gID = 0;
instrID = 0;
pFactID = 0;
};
These are in Instructor.cpp
void Instructor::showGameStatus()
{
}
int Instructor::createGame()
{
Game g;
}
CreateGame() initializes a game. I want that upon calling showGameStatus() I can print out all properties (eg gId, InstrId) of the Game g that initialized earlier etc.
Is it possible to access the properties of Game g that in another method?
This should do it. Class Instructor should inherit class Game:
class Instructor::public Game{
your code here
}
The short answer is: No.
The longer answer is this: If I understand correctly, what you want to accomplish, the problem is that the object g of type Game is held by a local variable inside the scope of your Instructor::createGame member function. Once that function is "done", i.e. the local scope ends, the object, which has automatic storage will be destroyed. It's gone. I don't know what the int means that you return, but no matter what it does, it doesn't hold an object of type Game.
Now, you probably want your createGame to return some type of handle to an actual Game object. Depending on your specific setting, it is your job to choose how to pass such an object around. For example, one way might be this:
Game Instructor::createGame() const { // 1
Game g;
// do stuff with g, perhaps?
return g;
}
Another might be:
std::unique_ptr<Game> Instructor::createGame() const { // 2
auto gptr = std::make_unique<Game>();
// do stuff with gptr, perhaps?
return gptr;
}
Or yet another:
std::size_t Instructor::createGame() { // 3
// Instructor has a member std::vector<Game> games
games.emplace_back();
// do stuff with games.back()
return games.size()-1;
}
There are countless other ways to pass the object around.
No matter what you choose you have to pass something to identify which Game object you are talking about back into your showGameStatus function, if you plan to have more than one Game object flying around (I assume you do).
auto some_handle = instructor.createGame();
// ... later ...
instructor.showGameStatus(some_handle);
This all holds true, if you want more than one object. Otherwise you might want to just add the object as a member of your Instructor type:
class Instructor {
private:
Game game;
public:
Instructor() : game() {}
// no createGame function, it is superfluous
void showGameStatus() const {
game.some_output_function();
}
};
Just inherit the Instructor Class into the Game Class and do your work...
I wrote my code like this inside a class to calculate max distance from source to node. Now I need to take it out of the class and have a similar function to calculate my distances but by using Djikstra. So, I would need to pass this city vector and source being one of my vertex ( this will loop over vertices ) and return a distance from this function back to class for my next computation. I am running out of time so help me.
int distanceToNearCity(int cityIdOfStore, const std::vector<City> & AllCities) const
{
// is there a store in this city ?
if (storeExists || cityId == cityIdOfProposedNewStore)
{
return 0; // 0 distance
}
int distance = TOOFAR; // initialise with more than max allowed
for (int i=0; i<connectingCities.size(); ++i)
{
int id = connectingCities[i];
if (AllCities[id-1].hasStore() || AllCities[id-1].getId() == cityIdOfProposedNewStore)
{
// we have a store (or proposed one) here, but is it's distance more than other stores ?
if (distances[i] < distance)
{
distance = distances[i];
}
}
}
return distance;
}
How can I pass these class objects to function which is public.Thanks!!
Well, accessing internal member variables from main is problably a bad design, breaks encapsulation, is a possible source of problems, thus not a good idea.
Solution 1
Let's say your class is called MyOriginal. Make distanceToNearCity virtual. Create a derived class MyDerived and rewrite distanceToNearCity so that implements Djikstra. In the derived class you can access the original member variables from MyOriginal, as long as they are public or protected. The user (main) does not need to know the implementation details.
Solution 2
Rewrite the original distanceToNearCity method so, that it has no side effects as it ware a static method. This means that it does not need access to any of the member variables. Pass all arguments to the method via parameters. I mentioned 'as it was a static method', since the method will not be the member of the original MyOriginal class. Make MyOriginal a template class, implement distanceToNearCity in an external class and pass this class as a template argument to MyOriginal. As a non member, you can implement any number of distance algorithms and pass them to the original class. This solution has the advantage, that the call to the 'virtual' method is known at the compile time, so it produces faster code.
template<class T> // T will contain distance computation
class MyOriginal
{
public:
void process()
{
.. // your staff
int distance = T::distanceToNearCity(necessary arguments); // call the external implementation
.. // rest of your staff
}
};
class OriginalDistance
{
public:
static int distanceToNearCity(necessary arguments); // your original implementation
};
class DjikstraDistance
{
public:
static int distanceToNearCity(necessary arguments); // another distance computation
};
int main(int argc, char *argv[])
{
MyOriginal<DjikstraDistance> myInstance;
myInstance.process(); // call processing, use DjikstraDistance::distanceToNearCity() inside
}
Solution 3
If you from some reason dislike both previous implementations, you can use a 'c' style solution. Create a type which represents a signature of the distanceToNearCity method.
Write 'distanceToNearCityOriginal' and 'distanceToNearCityDjikstra' functions. Pass a pointer to desired function as a paramter the MyOriginal::process method. C++ developers will dislike you.
typedef int (DistanceAlgo*)(necessary arguments); // pointer to a function which returns int
int distanceToNearCityOriginal(necessary arguments); // first implementation of distance
int distanceToNearCityDjikstra(necessary arguments); // second implementation of distance
class MyOriginal
{
public:
void process(DistanceAlgo algo)
{
.. // your staff
int distance = (*algo)(necessary arguments); // call the external implementation
.. // rest of your staff
}
};
int main(int argc, char *argv[])
{
DistanceAlgo algo = &distanceToNearCityDjikstra; // choose djikstra
MyOriginal myInstance;
myInstance.process(algo); // call processing, use distanceToNearCityDjikstra inside
}
I have a class "A" that take its variables' values from the application's GUI. let us say one of these variables is "X". then, in another class "B", I would like to call this "X" and pass its value to another function.
what I did is that I created an object of class "A" called "objectA" in class "B", and then called the value of "X" as follow:
// class A:
void classA::function1(int gui_value){
x= gui_value;
}
then in the another class:
//class B:
void classB::run(){
.
.
function2(/* I need to pass x here */);
.
.
}
both functions and x are defined in the header file correctly.
what I did is that I created an object of classA (let us say: objectA) in the header file and call the value of "x" in "function2" in "classB" using "objectA" as follow:
//class B:
void classB::run(){
.
.
function2(objectA->x);
.
.
}
Let us say "x" value equals "5", when I debug the value of "x" in function2, it gives me random number everytime i debug. So, I am just guessing that these random values are already exist in the memory, which means the value of "X" is not passed correctly.
I think, although the object is created, however it create a new instance of variable "x" everytime. i.e.: is not taking the value of "x" from classA, it is just create an object of classA with all its variables.
my problem is how to pass the vlaue of "x" that is obtained in classA directly to classB without creating a new instance of its variable ?
Update:
Thanks to doctorlove's answer, my code is now working fine. My problem was in initializing "objectA" after its creation and assigning a value to it. what I was doing is creating the object and passing it directly in "classB". That is why i was getting the random values as it was just a new object which have whatever value in the memory in the time of creation.
It is not clear what you are trying to do. If you have something like this...
class A
{
private:
int X;//ignoring any thing about encapsulation for now
};
class B
{
//...
public:
void DoSomething()
{
A objectA;
//makes objectA another A each time we get here, with X uninitialised
//use objectA.X which has random numbers in
}
};
this will behave similarly to the problem you describe. If you make objectA a member instead and initialise it properly it might do what you want. With class A as before,
class B
{
//...
private:
A objectA;
public:
B()
{
objectA.X = 42;
}
void DoSomething()
{
//use member objectA.X
}
};
EDIT
Clearly in my example I have pulled 42 out of nowhere. If you have a sensible value from the gui, send it to the constructor of B. If it changes you'll need a reference to it instead.
explicit B(int gui_value)
{
objectA.X = gui_value;
}
EDIT2
If you have an existing objectA someplace else, then pass that to the constructor
explicit B(const A & otherA)
: objectA(otherA)
{
}
If that's not possible, your design needs improving. Without any code to look at I cannot help any more.
let's say you got a class A with an private int variable i , and B with and private int variable X,
class A{
private:
int i;
// if you want to use x within A you have to declare the object here
B objectB;
.....
public :
int getI();
int setI();
};
// the second class B
class B(){
private :
int X;
......
public :
int getX();
void setX();
..
};
let'S say you have a main() function
int main (){
A objA;
B objB;
objB.setX(5);//X is now 5
objA.setI(objB.getx()); // i has the value of X which is 5
...
}
Since there is no compile time error on the creation of the objectA, the object is successfully been created.
To pass the variable, instead of using arrow operator use dot(.) operator
y = objectA.X
Heres my problem, if I pass a variable from class A to class B via function, then in class B pass that variable to other functions for testing then it works fine.
But if I pass the variable from A to B then try assigning it to a variable in class B, it gives the error for no reason
//Globals.h
enum TypeofObject { CIRCLE, SQUARE, RECTANGLE, DIAMOND };
//Object.h
#include "Globals.h"
class Object
{
void Update();
private:
TypeofObject currentObject;
CollisionDetection * gameCollision;
};
//Object.cpp
void Object::Update()
{
//Do stuff here
gameCollision -> testCollision(currentObject);
}
//CollisionDetection.h
#include "Globals.h"
class CollisionDetection
{
public:
void testCollision(TypeofObject currentObject);
private:
void checkObjects(TypeofObject currentObject);
TypeofObject currentObject;
}
//CollisionDetection.cpp
void CollisionDetection::testCollision(TypeofObject curObject)
{
currentObject = curObject; //<- If I have this then it gives access violation error
checkObjects(curObject); //<- Passing it from one function to the next works
//fine but I want to assign it to currentObject so
//it doesnt need to be passed
}
I assume the issue here is that Object::gameCollision has not been initialised. The CollisionDetection::testCollision function is called correctly because you can imagine member functions as regular function taking an extra hidden parameter:
void CollisionDetection_testCollision(CollisionDetection *this,
TypeOfObject curObject);
Given your definition, the function will run correctly up until the point where this is accessed:
currentObject = curObject; // this->currentObject = curObject
The line above is trying to set some memory at an offset from the this object. If this is not correctly initialised, the function will fail with an access violation.
I presume that checkObjects(curObject) does not fail because you are not accessing any of the data members of CollisionDetection in that function.
I have a variable, which is a member of one of my classes, that another is in need of, but I'm not sure how to effectively pass the value between them without using a global variable, which is something I'd like to avoid if at all possible. I know I could create an object, but that would invoke the constructor of the originating class which would execute a number of functions and write the needless results to memory, which would be wasteful of system resources.
Is there an easy way to pass this value between the two functions?
Update: The class that is in need of the variable, called no_of_existing_devices. The purpose of class Initialise is to open up a file and count the number of lines of test it contains, and place that number in the variable int no_of_existing_devices, which is then used by the Device::Device() to create an object for each
class Device
{
public:
void view_attribute_list();
void set_attribute();
Device();
};
Device::Device()
{
for (int count = 0; count < no_of_existing_devices; count ++)
{
// Create an object for each iteration, up to a maximum of no_of_existing_devices
}
}
The class of which this variable is a member
class Initialise
{
public:
int no_of_existing_devices;
bool initialisation;
string existing_device_list[100];
void initialise_existing_devices();
Initialise();
};
Initialise::Initialise()
{
no_of_existing_devices = 0;
}
void Initialise::initialise_existing_devices()
{
string line;
ifstream DeviceList;
DeviceList.open("devices/device_list");
while (true)
{
getline(DeviceList, line, '\n');
if (DeviceList.eof())
{
break;
}
++ no_of_existing_devices;
}
DeviceList.close();
DeviceList.open("devices/device_list");
for (int i = 0; i < no_of_existing_devices; i ++)
{
getline(DeviceList, line, '\n');
existing_device_list[i] = line;
}
Device existing_devices[no_of_existing_devices];
!initialisation; // Existing devices are now initialised
}
Okay, from what I understand:
You don't want to have a global
You don't want to have a static
You don't want to introduce a dependency between Device and Initialise
There is one other option, assuming something owns Device and Initialise, move the no_of_existing_devices up to there, then construct both Device and Initialise with a reference to this variable...
In a similar circumstance I was just passing the pointer to the member --- I had to invoke a member function then, so it was a pointer to the member function, http://www.parashift.com/c++-faq-lite/pointers-to-members.html
It's a bit messy, but it works :-).
If the variable in the originating class can hold a value without an instance of the class I would assume that the variable is static. If not create a public static member of the class. And use it in the target class.
Something like:
// .h file
class A
{
public:
static int a;
}
// .cpp file
int A::a = 123;
// .cpp file of class B
void B::foo()
{
cout << A::a;
}
If it is a class attribute (internal variable), then you can obtain a reference through a get method. Otherwise, you can use the friend keyword on the class you want to access the attribtue from the other For example, if you declare friend class B; on class A, the attributes of the class B will be accessible on the class A.
I suggest you use the first method in order to maintain your code OO pure ;)
Edit: of course, if you access through a reference there are no resources wasted :)
Edit 2: use a static method on Initialise class that returns the no_of_existing_devices and call Initialise::NoOfExistingDevices() on the Device class. If you want to resources use a pointer like this:
public static int* Initialise::NoOfExistingDevices() {
return &no_of_existing_devices;
}
By the way, I advise you to turn the variable private.