When we declare variables in a class and then when we assign the value of those variables, for example like this
class c {
public :
int x;
int x2;
c () {
x = 0;
x2 = 0;
scanf ("%d", &x); and now we're gonna input for example 10
}
};
each time the class is used, I mean each time the constructor is called, the value of x becomes 0 again since it is initialized as zero in the constructor. However if we don't initialize the value, there will be errors.
My question is that how can we keep the value of the variable when we call the constructor again and again so that it doesn't become zero ?
Edit:
void example () {
int i;
scanf ("%d", &i);
switch (i) {
case 1 : {Object ob1; system ("cls"); menu ();} // this object contains a value like 20
case 2 : {Object ob2; system ("cls"); menu ();}
}
}
There is another switch case in Object 1 which includes an option to go back to a main menu, now if I enter 1 again go back to object 1 I cannot see the value 20, it will be 0
The constructor is called only once for each instance so need to worry about that. You will never reset the value of x for a given instance to 0 because of its constructor.
Do you understand the difference between classes and objects/instances? Classes are merely a "Cookie-cutter" for objects. You don't "call" a constructor as such, but you create an instance of your class (which implicitely calls the constructor):
c myObj;
c anotherObj;
This code will create two instances of class c, both with their own version of x1 and x2. It's true that the constructor is run a second time when creating anotherObj, but it operates on totally different memory. So the values of x1 and x2 in myObj won't be touched.
Edit: The point of class member functions is that they operate on an implicit additional parameter named this. You could imagine that the "constructor call" actually looks like that (Just for illustrative purposes, not meant to be valid code):
c* this = malloc(sizeof(c));
constructor(c);
// With "constructor" actually being:
void ctor(c* this) {
this->x1 = 0;
this->x2 = 0;
// ..
}
That can also be achieved in C - but in C++, it happens implicitly, without you having to write code like this. You just write c newObj; or c* obj = new c;.
Apart from that: Member variables should be privat, and your mixing C library code (scanf) with C++ classes - use iostreams for input/output in C++.
You can store it in a static variable. Then read the value of x from that static variable.
Related
I'll try to make this as concise as possible and while I understand that these questions can be considered "basic" I have already looked at websites such as cplusplus.com and yolinux tutorials but i need somebody to explain this to me like I have just had a major head trauma..
1)
class Rectangle {
private:
int lineNumber; // LineNumber of the ACSIL Tool
float valueMax; // value of the higher limit of the rectangle
float valueMin; // value of the lower limit of the rectangle
public:
Rectangle(SCStudyInterfaceRef sc, int lineNumber, float valueMax, float valueMin);
int getLineNumber();
float getValueMax();
float getValueMin();
};
So int linenumber, valueMax and ValueMin are declared private members and thus are only accessible by members of the same class, thats fine. But what about the part that follows the "public:" ?
a) Is Rectangle(SCStudyInterfaceRef sc, int lineNumber, float valueMax, float valueMin); a function that is being overloaded? and if yes are int getLineNumber() etc part of that function or seperate members of the public part of the class?
2)
Rectangle::Rectangle(SCStudyInterfaceRef sc, int lineNumber0, float value1, float value2) {
lineNumber = lineNumber0;
int value2_greater_than_value1 = sc.FormattedEvaluate(value2, sc.BaseGraphValueFormat, GREATER_OPERATOR, value1, sc.BaseGraphValueFormat);
if (value2_greater_than_value1 == 1) {
valueMax = value2;
valueMin = value1;
} else {
valueMax = value1;
valueMin = value2;
}
}
int Rectangle::getLineNumber() {
return lineNumber;
}
float Rectangle::getValueMax() {
return valueMax;
}
float Rectangle::getValueMin() {
return valueMin;
}
a) I'm pretty sure that the functions defined inside the public part of the rectangle class are being "defined" here, or something along those lines.
b) I am really confused about what is happening here on the Rectangle::Rectangle(SCStudyInterfaceRef sc, int linenumber0, float value1, float value2) part. I understand the logic of what is happening within the function itself but i am confused about the paramters being input within the " ( ) " and how exactly this relates to what happenes inside the class public part. This really is the most important question that needs answering.
I have tried to be as concise and onpoint as possible, would appreciate some help in understanding this syntax.
Question 1
It's a constructor with 4 parameters.
int getLineNumber();
float getValueMax();
float getValueMin();
are all member functions in the class.
Question 2
The constructor defined earlier is called with 4 parameters. If no other constructor is defined then you'll have to instantiate the class with exactly 4 parameters, i.e:
Rectangle *rect = new Rectangle(sc, 100, 1.2, 6.8);
or simply:
Rectangle rect(sc, 100, 1.2, 6.8);
These parameteres are then used to "set the object in an initial state".
The member functions are used to get various values in their current (or final or only) state.
Rectangle::Rectangle is the class constructor. It is called whenever a Rectangle object is created. Read about constructors to understand better.
The constructor is setting initial values for the valueMax and valueMin member variables. It uses the parameters passed to the constructor to do this. Read about function parameters to understand better.
1) a: If no ctor function is declared, then the compiler writes a ctor for the class. But when a ctor is provided by the class no default ctor is written by the class and hence no overloading is taking place. Now if you go on and define one more ctor, may be because you want the object to be constructed in some other way, then you will have an overloaded ctor. In your case no overloading is taking place.
int getLineNumber() is just another member of the class.
2)
a: You are correct.
b: The parameters put inside "( )" are arguments list and if this function is called somewhere, then this list is type-matched and then function is called(in case of overloading). Now if you write a statement like:
Rectangle x(a, b, c, d);
then it means that your sc=a, lineNumber0=b, value1=c, value2=d for this function call.
while(true){
bool flag;
while(true){
if (conditions) {
flag=true;
break;
}
}
}
In this case, is the flag reset to false condition after it exits the inner while loop? It seems from the display of the console that it is still in true condition.
No, there is no "reset". There is no magic whatsoever. In fact, flag will not even be magically initialized to false for you, you'll have to do it yourself.
I think you're thinking of classic examples of scope and shadowing:
int a = 4;
//a is 4 here
{
int a = 3;
//a is 3 here
}
//a is 4 here
But there is no magic here, either. There are two different variables a which happen to share a name. a in the inner block refers to the second integer. If you could refer to the first integer, you'd be reading a completely different integer.
Here is some magic:
SomeClass x; //x's constructor is called
{
SomeOtherClass y; //y's constructor is called
} //y's destructor is called
Since y is automatic, it gets destroyed at the end of its scope. (So did the second a, by the way, only there was no way to tell.) If it has a destructor, it will be called. If its destructor does something fancy such as "resetting some flag", you'll see the results. (Only not through y, which will be gone.)
The fact that the {} have no if/while/function/etc. attached to them is irrelevant.
I have a thread-class Buffer (own made class), and many derived classes such as BufferTypeA, BufferTypeB...
Since I have to synchronize them in a certain order, I'm giving any of them an integer which represents the order to run certain task. I also have to know inside each thread Buffer which one is next to run the task, so I'm passing every BufferType a reference to an integer which all of them must share and I didn't want to make it Global.
I got lost at any point and I don't see where.
First I create all the BufferTypes from a class where I also define that shared integer as:
int currentThreadOrder;
And when creating the BufferTypes:
int position = 0;
if (NULL == bufferA) {
bufferA = new BufferTypeA(¤tThreadOrder, ++position,
waitCondition);
}
if (NULL == bufferB) {
bufferB = new BufferPos(¤tThreadOrder, ++position,
waitCondition);
}
if (NULL == bufferC) {
bufferC = new BufferRtk(¤tThreadOrder, ++position,
waitCondition);
}
Then, in BufferTypeA header:
class BufferTypeA: public Buffer {
public:
BufferTypeA(int currentThreadOrder,
int threadConnectionOrder = 0,
QWaitCondition *waitCondition = NULL);
//..
}
And in cpp file:
BufferTypeA::BufferTypeA(int currentThreadOrder, int threadConnectionOrder, QWaitCondition *waitCondition):
Buffer(currentThreadOrder, threadConnectionOrder, waitCondition) { }
Now I'll show Buffer header:
class Buffer: public QThread {
public:
Buffer(int ¤tThreadOrder,
int threadConnectionOrder = 0,
QWaitCondition *waitCondition = NULL);
//...
protected:
QWaitCondition *waitCondition;
int threadConnectionOrder;
int ¤tThreadOrder; // Shared address
}
And finally the cpp:
Buffer::Buffer(int ¤tThreadOrder, int threadConnectionOrder, QWaitCondition *waitCondition) {
this->threadConnectionOrder = threadConnectionOrder;
this->waitCondition = waitCondition;
this->currentThreadOrder = currentThreadOrder;
}
And the error I'm getting is error: uninitialized reference member Buffer::currentThreadOrder.
I'm embarrased to ask, because it's going to be a simple problem with pointers and addresses, but I can't see where the problem is, so please help.
When you create a class with a data-member that is a reference, the reference needs to be assigned a value in the constructor initializer list.
References have to be given a value when they are created, they are not pointers. They have to start with a value and that value cannot be changed (while the contents that is pointed to by that value can be changed).
Essentially you can think of a reference as an alias for an existing variable. You can't give a friend a nickname if you don't have a friend :)
RESPONSE TO COMMENT:
You don't "share a reference" between objects. Each object will have its own reference to the same variable. When you "pass by reference" you are telling the compiler that you want the variable in your function to actually be the variable in your outer scope, rather than creating a new variable by value. This means that you only have one variable at one memory location. The reference is just memory in some other place that forwards you to that same memory location.
Think of this as call forwarding... I can have 15 phone numbers in 15 different countries. I can set them all up to forward calls to my cell in the US. So, people are calling me no matter which number they call.
Each of your classes just has another reference to forward the "phone calls" or variable reads/writes to that same memory location. So, you're not sharing a reference between classes, you're making sure that each class HAS a reference to the same underlying memory location.
Back to the metaphore, each class won't have the same phone, but each class' phone will forward to the same number (variable) none-the-less which lets them all set/get the same value in the end.
RESPONSE II:
Here's a simple example to get your head going, it's pretty easy to apply to your classes. I didn't compile it but it should work minus a typo or two possibly.
class A
{
public:
A(int& shared) : m_shared(shared)
{
//No actions needed, initializer list initializes
//reference above. We'll just increment the variable
//so you can see it's shared in main.
m_shared += 7;
}
void DoSomethingWithIt()
{
//Will always reflect value in main no matter which object
//we are talking about.
std::cout << m_shared << std::endl;
}
private:
//Reference variable, must be initialized in
//initializer list of constructor or you'll get the same
//compiler error again.
int& m_shared;
};
int main()
{
int my_shared_integer = 0;
//Create two A instances that share my_shared_integer.
//Both A's will initialize their internal reference to
//my_shared_integer as they will take it into their
//constructors "by reference" (see & in constructor
//signature) and save it in their initializer list.
A myFirstA(my_shared_integer);
A mySecondA(my_shared_integer);
//Prints 14 as both A's incremented it by 7 in constructors.
std::cout << my_shared_integer << std::endl;
}
you pass a pointer int* as 1st argument to BufferTypeA, which expects and int, while you said in your question you meant to use a int&. To do this, the ctor of BufferTypeA should take a int& and initialise it in an initialisation list (i.e. not within the { } part of the ctor) like
class BufferType {
int &Ref;
public:
BufferTypeA(int& ref) : Ref(ref) { /* ... */ }
};
and in your construction of BufferA you must not pass an address, but the reference, i.e.
int counter;
Buffer = new BufferType(counter);
You want code like this:
Buffer::Buffer(
int ¤tThreadOrder0,
const int threadConnectionOrder0,
QWaitCondition *const waitCondition0
) :
threadConnectionOrder(threadConnectionOrder0),
waitCondition(waitCondition0),
currentThreadOrder(currentThreadOrder0)
{}
The reason is related to the reason you cannot write
const double pi;
pi = 3.14;
but can write
const double pi = 3.14;
A reference is typically implemented as a constant pointer, to which one cannot assign an address after one has initialized the pointer. Your version of the code assigns, as in the first pi example. My version of the code initializes, as in the second pi example.
I've probably become a bit to used to Java and am finding this harder than it should be. Heres what I have.
myObject[0] = new item1(this);
class item1
{
private:
int x;
int y;
public:
item1( passedPointer* pOne )
{
x = 5;
y = 5;
}
int returnX() { return x; }
int returnY() { return y; }
}
Then in another method I thought I could just say:
void check()
{
int y = item1.returnY();
int x = item1.returnX();
}
But I am getting the common error: a nonstatic member reference must be relative to a specific object.
There is only one instance of this class item1, what would be the best way to do this? This is just a simplified fragment of what I'm actually doing, not the actual code.
Item1 is a class. You have to create an instance of it before you can access its non-static members. Try looking here for some basic information.
void check(){
int y = item1.returnY;
int x = item1.returnX;
}
This would also be incorrect in Java, since neither returnX nor returnY are statics, you need an object on which to apply the operation, and you also need the parenthesis of the method call:
void check() {
item1 i;
int y = i.returnY();
int x = i.returnX();
}
Perhaps implementing the Singleton pattern would not do you harm, since you want only one instance of the object. You could declare the object as global or static to a function too, then get the values.
Then again, you could also declare the functions as static, and add another one to initialize the static values of the variables which need to be returned by those methods. There are a lot of solutions to this depending on your situation which can not be fully grasped by the short amount of code you have pasted.
You created an instance of class item1 with the line
myObject[0] = new item1(this);
Unlike JAVA, in C++ there are pointers and new returns a pointer to the object (so myObject[0] is a pointer to the instance) so you need the -> operator. To activate the method you should write:
myObject[0]->returnX();
If you wish to have only one instance than implement the class as a singleton.
the code below gives compilation error when I try to create test t[2];
because there is no default constructor for this.
But if I create Test t[2] = {test(1,2), test(2,3)}; Then it works fine.
1)But think of a situation, if we want to create more then 100 array element. We need to create 100 element in the curly braces like..
Test t[100] = {test(1,2), test(1,2)……/100 times/};
The above code is difficult to maintain.
One more solution is to create public member function which takes 2 integers and run in a loop. This solves the problem but i want to know any other good method.
2) If I create it using new
Test *t = new test[10];
I get compilation error(No default constructor). How to solve this.
class test
{
int _a;int _b;
public:
test(int a, int b);
void display();
};
int _tmain(int argc, _TCHAR* argv[])
{
test t[10];
for (int i = 0 ; i< 10; i++)
t[i].display();
}
In order to construct your 10 elements in the array the compiler somehow has to instaciate them through a constructor. For arrays only a default constructor (taking no arguments) can bes used, as you can not pass any arguments to the elements in the array. Therfor you have to proved a constructor
test::test()
taking no arguments.
In your example what do you expect to be displayed?
If you know that, you can write a Default CTor (one that has no parameters) and set your values to the defaults.
An example of the Default CTor:
// Variant 1: Use the initialization list
test()
: a(-1)
, b(-1)
{
}
// OR
// Variant 2: Do it in the CTor's body
test()
{
a = -1;
b = -1;
}
Note: You can write several CTors (it's called "overloading"). One that takes no parameters and sets default values and others that take parameters and set those values.
You can also define a constructor with default values for all parameters which will be used as the default constructor.
test(int a = 0, int b = 0) :_a(a), _b(b) {}
Since all parameters have default values, this constructor will be used as the default. Leaving out the initialization list or not initializing the member variables in the body of the constructor may give you random data values. Some systems may zero all memory allocations, but some do not.