Ok, on assigning a static variable declared in a constructor/function (I don't think it matters which) to a compile time defined value, it's as if the variables only been assigned once, see Example:
#include <iostream>
#define y 4
#define z 3
using namespace std;
class Foo
{
public:
Foo(int x)
{
static int i = x;
cout << i << endl;
}
};
int main()
{
Foo p(y);
Foo o(z);
return 0;
}
Expected output:
4
3
Actual output:
4
4
I couldn't find anything on searching, though if this is a dupe just let me know and i'll close the question.
A static local variable is initialized only once when the function it resides in is entered for the first time. So only the first initialization happens, and all further ones are ignored.
Here's your program, modified to illustrate it.
#include <iostream>
#define y 4
#define z 3
using namespace std;
struct Bar {
int i;
Bar(int i) : i{i}
{
cout << "Bar::Bar with " << i << '\n';
}
};
class Foo
{
public:
Foo(int x)
{
static Bar b = x;
cout << b.i << '\n';
}
};
int main()
{
Foo p(y);
Foo o(z);
return 0;
}
If you want each subsequent call to modify i, you need to assign into it:
static int i; // default initialize i.
i = x; // assign a new value into i
Related
I tried the following code:
#include <iostream>
using namespace std;
int main()
{
char string[4]='xyz';
return 0;
}
Since string is a keyword the compiler should give error but it runs fine. Can anyone explain why it compiles successfully.
string is not a keyword.
It's the name of a type declared in the standard library.
When you give it a name, you're doing something called shadowing. This is more clear in the following example:
{
int x = 0;
{
int x = 5;
std::cout << x << std::endl;
}
std::cout << x << std::endl;
}
What gets printed?
Well, 5 first then 0.
This is because the x in the second scope overrides the x from the first. It "shadows" the first declaration.
This works with typenames as well:
struct MyStruct {
int x;
};
...
{
...
int MyStruct = 10;
...
}
Here, MyStruct gets overridden within that scope.
That same thing happens in your example with std::string
I have broken down my issue into a small simple program.
I have a class myclass I have created in a separate .cpp file "classes.cpp" and declared in the header file "classes.h". myclass contains a variable a of which is initialized when instantiated. This makes variable a = 5.
My overall goal is to create a class in a separate .cpp file declared in a .h file which I can create multiple instances of in my main() program. The problem I am having is this.
In my main() function I create an instance of myclass called first.
my main program shows the variable a is set to the number 5.
If I want to change that number using a static function (and it has to be a static function as this relates to something much bigger in another program I am writing). I call the static function directly and in that static_function I create an instance of myclass and call the non_static_function because static functions have no implicit 'this' connecting them to an object.
In my non_static_function I change the value to the number 8. The problem is that the value of variable 'a' in 'first' remains at 5 when I want it to be 8. I need to change the value using first->static_function(8) and not by first->a = 8. . How can I do this?
Code below:
**main.cpp**
#include <iostream>
#include "classes.h"
using namespace std;
int main()
{
myclass *first = new myclass();
cout << "Myclass variable a is = " << first->a << endl;
first->static_function(8); // trying to change myclass variable 'a' to 8.
cout << "But" << endl;
cout << "the actual value of a is still: " << first->a << endl;
}
**classes.h**
#ifndef CLASSES_H_INCLUDED
#define CLASSES_H_INCLUDED
class myclass
{
public:
int a;
myclass();
void non_static_function(int x);
static void static_function(int x);
};
#endif // CLASSES_H_INCLUDED
**classes.cpp**
#include <iostream>
#include <cstdlib>
#include "classes.h"
using namespace std;
myclass::myclass()
{
a = 5;
}
void myclass::non_static_function(int x)
{
a = x;
cout << "The value for variable 'a' was 5 but is now: " << a << endl;
}
void myclass::static_function(int x)
{
myclass *p = new myclass();
p->non_static_function(x);
}
If you want every instance of myclass to have its own a and you want to call a static function to change it then you need to pass the instance you want changed to the static function. A static function can only modify static members of a class or the members of an instance that is inside its scope. Non static member functions can change any variable that is a member of the class.
class Foo
{
private:
int bar;
public:
static void static_function(int value, Foo & foo) { foo.bar = value; }
void non_static_function(int value) { bar = value; }
};
int main()
{
Foo foo;
Foo::static_function(8, foo);
// now bar will have the value of 8
foo.non_static_function(20);
// now bar will have the value of 20
}
I have finally found a way to deal with this small problem. Above the 'myclass' definition in classes.cpp I declare a 'myclass' variable
myclass *tgt; . Then in my constructor for 'myclass' I just allocate the instantiated object to a my global myclass variable of which I can access from the myclass definition tgt = this; Now I can use tgt in my static function to call the non_static_function in my 'myclass' definition and it all works perfectly.
NathanOliver, you are correct in saying that I need a class instance but the way I have done it here suits my needs. Passing the instance of myclass is certainly another way of doing this but it would require a global function above my 'myclass' definition.
Thanks for the help.
**main.cpp**
#include <iostream>
#include "classes.h"
using namespace std;
int main()
{
myclass *first = new myclass();
cout << "Myclass variable a is = " << first->a << endl;
first->non_static_function(8); // trying to change myclass variable 'a' to 8.
cout << "But" << endl;
cout << "The actual value of a is still: " << first->a << endl;
myclass *second = new myclass();
cout << "For the 'second' class the variable a is: " << second->a << endl;
second->non_static_function(23);
cout << "After calling the static function from 'second' the value of a is: " << second->a << endl;
cout << "And first->a is still: " << first->a << endl;
}
**classes.h**
#ifndef CLASSES_H_INCLUDED
#define CLASSES_H_INCLUDED
class myclass
{
public:
int a;
myclass();
void non_static_function(int x);
static void static_function(int x);
};
#endif // CLASSES_H_INCLUDED
**classes.cpp**
#include <iostream>
#include <cstdlib>
#include "classes.h"
using namespace std;
myclass *tgt; // *Add a global myclass variable above the myclass
definition*
myclass::myclass()
{
tgt = this; // *In the constructor allocate the instantiated class
//from main() to "tgt" .*
a = 5;
}
void myclass::non_static_function(int x)
{
a = x;
// Now see that the value of a is changed.
cout << "The value for variable 'a' was 5 but is now: "<< this->a << endl;
}
void myclass::static_function(int x)
{
tgt->non_static_function(x);
}
How could I keep an object valid in a different class? Here is an example below.
This code would give as a result on the screen:
2
2
What I want is to give me this:
2
3
In other words, I desire object Bita (or even the whole class two) to acknowledge object Alpha and not create a new object.
Is there a way to include the object Alpha to object Bita ? Please be simple because I am a beginner.
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
class one
{
int a, b;
public:
one() { a = 2; }
int func()
{
return a;
}
void func2()
{
a = 3;
}
};
class two
{
int z, b;
public:
void test();
};
void two::test()
{
one Alpha;
cout << Alpha.func() << '\n';
}
int main()
{
one Alpha;
cout << Alpha.func() << '\n';
Alpha.func2();
two Bita;
Bita.test();
return 0;
}
Each instance of an object has its own values for its member variables. So when you declare two Bita, and call Bita.test(), test() creates its own object of class Alpha inside of it, with its own value, which is still at 2, prints that, and then that Alpha object goes out of scope and is removed from the stack as test() completes.
What you say you have in mind to do here is to have class one have what is called a static member variable. Add the keyword static:
static int a;
And then a will behave as you intend.
One explanation of this is here: http://www.learncpp.com/cpp-tutorial/811-static-member-variables/
One solution would be to pass the object by reference you method two::test like this
class two
{
int z, b;
public:
void test(one& a);
};
void two::test(one& a)
{
cout << a.func() << '\n';
}
And then call it in main
Bita.test(Alpha);
So the full code will be
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
class one {
int a, b;
public:
one() { a = 2; }
int func() { return a; }
void func2() { a = 3; }
};
class two {
int z, b;
public:
void test(one&);
};
void two::test(one& a) {
cout << a.func() << '\n';
}
int main() {
one Alpha;
cout << Alpha.func() << '\n';
Alpha.func2();
two Bita;
Bita.test(Alpha);
return 0;
}
I've just made a template to detect if a data member of a class is static defined or not. The accessibility of the member isn't what it should be concerned about(Assuming the member is always accessible by the template) in this post. Here is the code with any symbols for testing:
#include <conio.h>
//#include <stdio.h>
#include <iostream>
struct A1
{
int a;
};
struct A2
{
static int a;
};
int A2::a{};
template < class My_Type >
struct TestStatic
{
template < typename raw_ty > static char fTest(...);
template < typename class_ty, typename arg_ty = decltype(class_ty::a) >
static int fTest(int, arg_ty & = class_ty::a);
enum nRes { result = sizeof(fTest<My_Type>(0)) - 1 };
};
int main(void)
{
int i;
i = TestStatic<A1>::result;
std::cout << i << std::endl;
i = TestStatic<A2>::result;
std::cout << i << std::endl;
_getch();
return(0);
}
The question is when it was built with g++ 4.8 the compiling passed but got the result as two '3's rather than one '0' and another '3'. Is there anything wrong?
Your approach is fundamentally flawed, because decltype(T::x) is perfectly valid for non-static members:
#include <iostream>
struct T
{
int x;
};
int main()
{
std::cout << sizeof(decltype(T::x)) << '\n';
}
// Output: 4
You can get what you want with std::is_member_pointer:
If T is pointer to non-static member object or a pointer to non-static member function, provides the member constant value equal true. For any other type, value is false.
#include <iostream>
#include <type_traits>
struct T
{
int x;
};
struct S
{
static int x;
};
int main()
{
std::cout << !std::is_member_pointer<decltype(&T::x)>::value << ' ';
std::cout << !std::is_member_pointer<decltype(&S::x)>::value << '\n';
}
// Output: 0 1
This works because access to members through the :: syntax results in a pointer-to-member only if the member is not-static; it is of course a normal variable access when the member is static.
A point from ISO draft N3290 :
Unqualified Name Lookup :section 3.4.1, para 14:
If a variable member of a namespace is defined outside of the scope of its
namespace then any name that appears in the definition of the member
(after the declarator-id) is looked up as if the definition of the member
occurred in its namespace.
ex:
namespace N {
int i = 4;
extern int j;
}
int i = 2;
int N::j = i; // N::j == 4
Is there any other possiblitly to prove this point other than using 'extern' keyword
can u give some other examples ... other than extern
Another example which doesn't use extern keyword:
//demo.cpp
int i = 100;
namespace N
{
int i = 200;
struct A
{
static int m;
};
}
int N::A::m = i; //i is 100 or 200?
int main()
{
cout << N::A::m << endl; //what will it print?
}
Output:
200
Online demo : http://www.ideone.com/pRVAb
This code doesn't use extern yet it more or less proves the point. Note that it doesn't define variable outside the namespace, it instead defines function outside the namespace.
//demo.cpp
int i = 100;
namespace N
{
int i = 200;
struct X{};
void f(const X&);
}
void N::f(const X&)
{
cout << i << endl; //what will it print?
}
int main()
{
N::X x;
f(x); //use argument-dependent lookup (ADL) to find the function!
}
Output:
200
Online demo : http://www.ideone.com/KCqUV
I added ADL to make it more interesting!
Another example is regarding the definition of a static member in class.
// header
namespace N {
const int i = 4;
class A
{
public:
static int m_i;
};
}
// source file
int i = 2;
int N::A::m_i = i; // N::A::m_i == 4
int main(int argc, char* argv[])
{
cout << N::A::m_i << endl;
return 0;
}
// header.h
struct X { void bar () {} };
namespace N {
struct X { void bar () {} };
void foo(X *p = new X);
}
// implementation.cpp
#include"header.h"
N::foo(X* p) { p->bar(); } // N::X::bar() called
This example is without using extern. (though it's implied).