I have a problem. I am currently working on a small example in c++ and can't figure out the explanation. Here is my problem:
#include <iostream>
using namespace std;
class X{
int& i ; /* int i; */
public :
X(int k=100):i(k){ }
X(`const` X& x):i(x.i){}
void setI(int k){i=k;}
int getI(){cout <<"adresse: "<< &i << " Contenue: "<<i<<endl ; return i;}
};
int main(){
int i =7;
X a(i);
a.getI();
a.setI(5);
a.getI();
cout << "the value of i is: " << i << endl;
X b(a);
b.getI();
cout << "the value of i is: " << i << endl;
X c;
c.getI();
a.getI();
return 0;
}
So what I dont understand is why does the variable member i in the
class X work like a class variable? I have searched online and found
that it is called agregation and that it is used for some reasons but
I can not understand why does it happen? How does the compiler do
that?
Could you please explain this to me. Thanks in Previous.
Your code has undefined behaviour, it doesn't have to work in any way at all.
Here's the problem
class X {
int& i;
public:
X(int k = 100) : i(k) {}
...
};
k is a local variable, a parameter to the constructor. It no longer exists once the constructor has exitted.
But your code takes a reference to that local variable. So your class ends up with a reference to an object wheich no longer exists. This is undefined behaviour.
PS I'm not sure what you mean by class variable vs. member variable. To me those terms mean the same thing. But whatever strange behaviour you are seeing, it's explained by the undefined behaviour that your program has, as described above.
PPS I see class variable means static member variable, makes sense, so ignore the previous paragraph.
Related
I'm an absolute newbee when it comes to programming and I'm trying to teach myself the basics by just solving some easy "problems" in C++.
I have searched the web for an exact answer to my question before posting it here and haven't found one so far, however that may be because of (1).
So, what I'm looking for is a way to declare a class member that gets automatically calculated from other members of the same class, so that the calculated class member can be used just like an explicitly defined class member would. For example imagine a struct called creature that has the properties/members creature.numberofhands, creature.fingersperhand and finally the property creature.totalfingers that automatically gets calculated from the above members.
Heres an example of the closest I got to what I wanted to achieve:
#include <iostream>
typedef struct creature {
int numberofhands;
int fingersperhand;
int totalfingers();
} creature;
int creature::totalfingers()
{
return numberofhands * fingersperhand;
};
int main()
{
creature human;
human.numberofhands = 2;
human.fingersperhand = 5;
printf("%d",human.totalfingers());
return(0);
}
What's really annoying me about this, is that I have to treat the calculated one DIFFERENTLY from the explicitly defined ones, i.e. I have to put "()" after it.
How can I change the code, so I can use: human.totalfingers without ever explicitly defining it?
The simplest option would be to use public member functions and make the actual properties hidden.
Something like this:
class Creature {
public:
Creature(int numhands, int fingersperhand) // constructor
: m_numhands{numhands}, m_fingersperhand{fingersperhand}
{ }
int fingersPerHand() const { return m_fingersperhand; }
int numberOfHands() const { return m_numhands; }
int totalFingers() const { return numberOfHands() * fingersPerHand(); }
private:
const int m_numhands;
const int m_fingersperhand;
};
The private member variables are an implementation detail. Users of the class just use the three public member functions to get the different number of fingers after construction and don't need to care that two of them are returning constant stored numbers and the third returns a calculated value - that's irrelevant to users.
An example of use:
#include <iostream>
int main()
{
Creature human{2, 5};
std::cout << "A human has "
<< human.totalFingers() << " fingers. "
<< human.fingersPerHand() << " on each of their "
<< human.numberOfHands() << " hands.\n";
return 0;
}
If - as per your comment - you don't want to use a constructor (although that's the safest way to ensure you don't forget to initialize a member), you can modify the class like this:
class CreatureV2 {
public:
int fingersPerHand() const { return m_fingersperhand; }
int numberOfHands() const { return m_numhands; }
int totalFingers() const { return numberOfHands() * fingersPerHand(); }
void setFingersPerHand(int num) { m_fingersperhand = num; }
void setNumberOfHands(int num) { m_numhands = num; }
private:
// Note: these are no longer `const` and I've given them default
// values matching a human, so if you do nothing you'll get
// human hands.
int m_numhands = 2;
int m_fingersperhand = 5;
};
Example of use of the modified class:
#include <iostream>
int main()
{
CreatureV2 human;
std::cout << "A human has "
<< human.totalFingers() << " fingers. "
<< human.fingersPerHand() << " on each of their "
<< human.numberOfHands() << " hands.\n";
CreatureV2 monster;
monster.setFingersPerHand(7);
monster.setNumberOfHands(5);
std::cout << "A monster has "
<< monster.totalFingers() << " fingers. "
<< monster.fingersPerHand() << " on each of their "
<< monster.numberOfHands() << " hands.\n";
CreatureV2 freak;
freak.setFingersPerHand(9);
// Note: I forgot to specify the number of hands, so a freak get
// the default 2.
std::cout << "A freak has "
<< freak.totalFingers() << " fingers. "
<< freak.fingersPerHand() << " on each of their "
<< freak.numberOfHands() << " hands.\n";
return 0;
}
Note: all of the above assumes you are using a modern C++14 compiler.
What you have described is one of the reasons why encapsulation and "member variables should be private" is the recommended way of doing things in C++.
If every variable is accessed through a function, then everything is consistent, and refactoring from a member variable to a computation is possible.
Some languages, like C# or D, have the concept of "properties", which provide a way around the issue, but C++ does not have such a construct.
For fun, the proxy way to avoid extra parenthesis, (but with some extra costs):
class RefMul
{
public:
RefMul(int& a, int& b) : a(a), b(b) {}
operator int() const { return a * b; }
private:
int& a;
int& b;
};
struct creature {
int numberofhands;
int fingersperhand;
RefMul totalfingers{numberofhands, fingersperhand};
};
Demo
Note: to use RefMul with printf, you have to cast to int:
printf("%d", int(human.totalfingers));
That cast would not be required if you use c++ way to print:
std::cout << human.totalfingers;
If you're after consistency, you can make your changes the other way around. Replace the two member variables with constant methods which simply return copies of the member variables. That way, the way you access data is consistent and you don't have to worry about some code changing the values of the member variables when it shouldn't.
Others have provided very good answers. If you are looking for consistency, probably the easiest way is to make use of member functions (as #Jesper Juhl has answered).
On the other hand, if you strictly want to use class members that are calculated automatically from other members, you can use properties. Properties (as are defined in C# and Groovy) are not a standard feature of C++ but there are ways to implement them in C++. This SO question has a very good overview of the ways that properties can be defined and used in C++. My favorite way of defining properties is taking advantage of Microsoft-specific extension for properties in Visual C++ (obviously, this approach is specific to Microsoft Visual C++). A documentation of properties in Visual C++ can be found in MSDN. Using properties in Visual C++, your code can be modified to:
struct creature {
int numberofhands; // use of public member variables are generally discouraged
int fingersperhand;
__declspec(property(get = get_totalfingers)) // Microsoft-specific
int totalfingers;
private:
int fingers;
int get_totalfingers()
{
return numberofhands * fingersperhand; // This is where the automatic calculation takes place.
}
};
This class can be used like this:
#include <iostream>
int main()
{
creature martian;
martian.numberofhands = 2;
martian.fingersperhand = 4; // Marvin the Martian had 4!
// This line will print 8
std::cout << "Total fingers: " << martian.totalfingers << std::endl;
return 0;
}
As I said earlier, properties are not a standard feature of C++ but there are ways to get them in C++ which either rely on smart tricks or using compiler-specific features. IMHO, using simple functions (as #Jesper Juhl described) is a better alternative.
For th following code:
#include <iostream>
class Test
{
public:
int i;
void get();
};
void Test::get()
{
std::cout << "Enter the value of i: ";
std::cin >> i; // Line 1
}
Test t;
int main()
{
Test t;
t.get();
std::cout << "value of i in local t: "<<t.i<<'\n';
::t.get();
std::cout << "value of i in global t: "<<::t.i<<'\n';
return 0;
}
Though I know what is happening in the above code i.e. the values are assigned to the local and global t , I am confused by the line 1 as I am unable to understand how the value received from the user by the line 1 is getting assigned to the t.i or ::t.i .
It would be much appreciated If someone can help me explain **behind the scene of above problem **.
Test::get() is a member function.
Inside a member function, you can name any member variable of that class, and it'll affect the object you called the function on.
Read the chapter in your C++ book about classes.
I have the next code (make it small & simple),
Why did I get the speed += working, although the speed wasn't initialized at all?
#include <iostream>
using namespace std;
class Vehicle {
protected:
int speed;
public:
virtual void repair(int j) {
cout << "Vehicle " << j << endl;
if (repair())
{
speed += j;
cout << "Speed:" << speed;
}
}
int repair(){ cout << "Vehicle repair " << endl; return 1; }
};
void main() {
Vehicle v; //Car c; CityCar cc;
Vehicle * vp; //Car * cp;
vp = &v;
vp->repair(1);
}
In C++ you can always use uninitialized variables, at most you'll get a warning. Except if you set a "warning as errors" option, in which case you'll get an error, obviously.
Different compilers do different things, so in your case, depending on the compiler and compiler options, you can get a warning, or not.
See this question.
Note that in fact by creating an object pointer
and then carry out an assignment operator on it
you actually initialized it in junk value
try this:
Int x,*a;
a=&x;
cout<<*a;
Speed is a type of int, and int is a built-in type.If an object is of built-in type, then value-initializing it sets it to zero, and default-initializing it gives it an undefined value.
In your case, speed has an undefined value. Adding this constructor with constructor initializer in public section should work for you:
Vehicle() : speed{0} {}
Here's an extremely basic example of my question.
#include <iostream>
#include <string>
using namespace std;
int x;
void test(int x) {
x += 3;
cout << x << endl;
}
int main() {
test(x);
cout << x << endl;
return 0;
}
the output is:
"3" (new line) "0"
How can I specify inside of the "test()" function that I want the class's 'x' variable to have the 3 added to it instead of the temp variable inside of the function?
In java you specify that you're dealing with the function/method's variable by using '"this". Is there a similar way to do this in C++?
In your case you can use :: to specify to use global variable,
instead of local one:
void test(int x) {
::x += 3;
cout << ::x << endl;
}
And it is not class member or so on just global and local.
In the C++ language, create a class or struct and you can use this->x the same as this.x in the Java language.
First of all, thank you for stating that you come from Java. This will help us a lot in terms of helping you!
Now, let's analyze your code
#include <iostream>
#include <string>
using namespace std;
Including some headers, using the std namespace (not recommended, BTW), everything's okay here.
int x;
You declare a variable named x of type int at global scope, with an initial value of zero (this only applies to objects at global scope!).
void test(int x) {
x += 3;
cout << x << endl;
}
You declare a function test that takes a parameter x of type int and returns void (a.k.a: nothing). The function increments the value of its intenral x variable by 3, then prints that to standard output by means of std::cout. Just to be clear, once you declare the int x parameter, it "hides" the int x at global scope, thus if you want to access the later, you have to use another way (see below).
int main() {
test(x);
cout << x << endl;
return 0;
}
You declare the special main function, taking no parameters and returning int. The function calls test with the global int x as argument, then prints the value of the global x to the standard output by means of std::cout, and finally returns zero, indicating successful execution.
Now, you have a big misconception, that you can attribute to the single-paradigm design of the Java language. In Java, there's no concept of "global functions", not to even say there are no "functions" at all. You only have "classes" with "methods".
In C++, this is not the case. The C++ language is a multi-paradigm one; it allows you to do imperative programming, structured programming, object-oriented programming, and even functional programming (you're not expected to have understood that last sentence completely)! When you declare anything without specifying an scope, it's said to lie in the global scope. The global scope can be accessed by anything, anywhere. In the example you presented there are no classes involved!
In the global scope, something like void test(int) is not a method, but a function. There's no class "owning" that function; let's say it's of "everyone" ;). A function is just a block of code that you can reuse by giving it arguments, if the function has them at all. In C++, you use classes to encapsulate data and corresponding code in a single "packed" black-box entity, not for, well, anything, like in Java.
Now, (this is somewhat like Java, but be careful!), when you pass a "plain" object, such as an int or something more funky and complex like std:: (you were not expected to understand that...) to a function, that function gets a copy of that object. The int x in test is not the same as the one main passed to it. If you assign to it inside test, you'll notice main "sees no difference". In Java, this applies too, but only to the fundamental types like int, but in C++ it does for all types.
If you want to be able to change the variable you got, just use references. You get a reference of any type T by typing T&. So, if you assign to a int& x inside the now modified test, main will "see" all changes.
Finally, there's the :: operator. It's used to access stuff in some scope from, well, other scopes. It has the form namespace-or-class::stuff. So for example, std::cout refers to identifier cout in namespace std. There's a special case: if the left operand is not given, :: accesses the global scope. This is useful whenever you "hide" something from the global scope. So, for example, in test, you could say ::x, and that would refer to the x in the global scope!
void test(int x) {
// ...
::x += 123;
}
Edit: If you're curious, you can take a glance at how classes in C++ work with this (I won't explain it, because that's off-topic)...
#include <iostream>
int x = 0;
class MyClass {
private:
int x;
public:
MyClass() : x(0) {}
void test(int x) {
this->report(x);
std::cout << "Doing some magic...\n";
this->x += x;
this->report(x);
}
void report(int x) {
std::cout << "this->x = " << this->x << '\n';
std::cout << "x = " << x << '\n';
}
};
int main() {
MyClass c;
c.report();
x += 123;
c.test(x);
x += 456;
c.test(x);
c.report();
}
This is a newbie C++ question. I was reading the "Function object" article in Wikipedia. The article has an example in C++ similar to the following:
struct printClass {
int &count;
printClass(int &n) : count(n) {}
void operator()(int &i) const {
count++;
cout << i << "[" << count << "] ";
}
};
int main(int argc, char** argv) {
vector<int> a(5, 7);
a[4] = -1;
a.resize(10, 3);
int state = 0;
for_each(a.rbegin(), a.rend(), printClass(state));
}
I have 2 questions:
Why does it fail to compile when count is a regular variable not a reference type? Demo
Why does it fail to compile it I change the ctor to the following? Demo
printClass(int &n) { count = n; }
Thanks.
EDIT: Thanks for explaining. I see that the following version works, too. Is there a reason for chosing one over another?
struct printClass {
int count;
printClass(int n) { count = n; }
void operator()(int &i) {
count++;
cout << i << "[" << count << "] ";
}
};
EDIT: Based on iammilind's reply, here is the 3rd version that works too using const_cast<int &>.
struct printClass {
int count ;
printClass(int n) : count(n) {}
void operator()(int &i) const {
const_cast<int &>(count)++;
cout << i << "[" << count << "] ";
}
};
(1) Why does it fail to compile when count is a regular variable not a
reference type?
This is a very interesting question. The question should be rather, why the code compiles when count is declared as a reference. :)
The regular variable fails because int count is not modifiable inside a const qualified function operator()(int &i) const;.
References are little different. In your code you are declaring the method as const, which means that count which is referring to i, now cannot refer to anything else.
But that's anyway not possible due to nature of references :). One cannot change reference binding after the initialization.
operator() just checks whether you are changing the binding of count to anything else or not? And the answer is always no. Because count++ changes the value referred by count and not the binding.
In your code, it doesn't matter if a member method is const or not when it comes to int& count.
Relate int& count; to int* const p_count; and try to simulate the situation on your own.
(2) Why does it fail to compile it I change the ctor to the following?
CountFrom(int &n) { count = n; }
Because reference must be assigned to a variable while initialization. In simple example;
int i, &r; // error, because 'r' not initialized
r = i; // this is not initialization but a copy
On a side note, you should be extra careful when you are dealing with reference variables inside a class. Because it's easy to mess up with their scope and validity.
For example, here the validity of count is dependent on the scope of i.
Edit: After your 2nd edit, it's very trivial to know why that version works.
Because count is now a simple variable. It can be skipped from initialization in the initializer list of the constructor unlike reference.
Moreover the const correctness of the operator() is gone, so any member variable of the class can now be modified inside it.
You should choose a const version of the member method, if you want to state that no class member "must" change inside it (unless any variable is mutable or you use const_cast). In all other cases use the normal version of the member method. They both can co-exist as well depending on your business logic. This is a bit of a broad question and it's worth to have another thread for this.