I just want to access the static member of a template class. I know there are many posts here on how to initialize it, but my problem is printing its value.
#include<iostream>
using namespace std;
template<typename T>
class X
{
static int i;
};
//There are answers everywhere on this site to initialize it
template<typename T>
int X<T>::i = 5;
//But Please help me to access it
int main()
{
X<int> x;
//Problem below I just want to access it
cout << endl << X<int>::i << endl;
return 0;
}
Another case where the compiler error message contains the answer. E.g. gcc says
main.cpp:13:5: error: 'int X::i' is private
and of course you cannot access private fields from outside the class. Make it public instead.
Related
I am so confused right now...
Here is the code that I will be talking about:
main.cpp:
#include "CustomVector.h"
#include <iostream>
int main() {
CustomVector<int, 15> hello{};
std::cout << hello.size() << '\n';
return 0;
}
CustomVector.h:
#pragma once
template<typename T, int S>
class CustomVector {
private:
T arr[S];
int size;
public:
CustomVector() : arr{}, size{ S } {}
// Methods
int size() const {
return size;
}
};
As you can see I am trying to use the size() method that I have in my class definition, which there shouldn't be a problem with, right..? But when I try to use it in main.cpp and try to print it out to the console, it is giving me the compiler error which my question title has. Why could this be, this has never happened to me before. I would think there is some sort of "redefinition" somehow, but how could that be, there couldn't be a redefinition if it is in my own user-defined class?
I am new to c++ and experimenting with classes and static variables.
I have found the solution to making the code run but I am not sure why this works and why my previous method did not
#include <iostream>
using namespace std;
class Person {
static int id;
public:
void createPerson() {
id++;
cout << id << endl;
}
};
int Person::id = 0;
int main() {
Person Person1;
Person Person2;
Person1.createPerson();
Person2.createPerson();
}
I am wondering why I must declare the value of id outside the class. And why I cannot have something like..
class Person {
static int id = 0;
public:
void createPerson() {
id++;
cout << id << endl;
}
};
static data members are not parts of objects, so you need to tell the compiler explicitly in which translation unit to store them by providing that definition.
Note that static data members of class templates can be defined in the header files.
In C++17 a static data member can be declared as inline, so that no out-of-line definition is necessary.
Adding the inline keyword will do the job. Simply change your line to:
static inline int id = 0;
Another possibility would be, but only if your value is constant, to declare it like this:
static inline constexpr int id = 0;
This is the preferred way for declaring global constants instead of using #defines.
Within a class definition static data members are declared bur not defined. So you may even to use a non-complete type in a declaration of a static data member inside a class definition.
For example
struct A
{
static int a[];
};
int A::a[10];
Here in this example the declaration of the data member a within the class definition has an incomplete array type (the number of elements of the array is unknown).
Starting from C++ 17 you may declare a static data member as an inline member. For example
class Person {
inline static int id = 0;
public:
void createPerson() {
id++;
cout << id << endl;
}
};
In this case you may initialize it in the declaration inside the class definition.
Otherwise you may initialize a static data member within a class definition only if it is declared as having an integral type and has the qualifier const or the specifier constexpr (in the last case the static data member will be an inline declaration).
But if a static data member is declared as a const object nevertheless you have to define it outside the class if for example you will try to get the address of the static data member. For example this code is invalid
#include <iostream>
using namespace std;
class Person {
const static int id = 0;
public:
void createPerson() {
cout << &id << endl;
}
};
int main()
{
Person Person1;
Person Person2;
Person1.createPerson();
Person2.createPerson();
}
As there is the address of the static data member is taken then you have to define the static data member.
#include <iostream>
using namespace std;
class Person {
const static int id = 0;
public:
void createPerson() {
cout << &id << endl;
}
};
const int Person::id;
int main()
{
Person Person1;
Person Person2;
Person1.createPerson();
Person2.createPerson();
}
This program will compile.
I have a pretty basic class with member functions and private data, but I want the print function not to be a part of the class member functions. I remove it from the class and declare it as a friend and it works when called directly from main.cpp, but when a class member function calls it internally it is not declared. I know being a friend gives it access to data, but how do I make it available to the member functions? Is it possible?
//HEADER FILE
#include<iostream>
using namespace std;
static const int ArrSize=3;
class TicTacToe
{
//friends
friend void printBoard(char [][ArrSize]);
//member functions
public:
void makeboard();
void isValidMove();
void isWinner();
void getMove();
//data members
private:
int pRow, pCol, player;
bool validMove, winner;
char TTTarray[ArrSize][ArrSize];
};
void TicTacToe::getMove()
{
// some internal code for determining if proper input
// calls printBoard() to show what move was made.
printBoard(0);
void printBoard(char TTTarray[][ArrSize])
{
int i;
for(i=0;i<3;i++)
{
cout << TTTarray[i][0] << " " << TTTarray[i][0] << " " << TTTarray[i][2] << endl;
}
}
// MAIN.CPP FILE
#include <iostream>
#include "TicTacToe.h"
using namespace std;
int main()
{
TicTacToe a;
a.makeBoard();
printBoard(0);
a.getMove();
return 0;
}
At the point where you use printBoard inside getMove, printBoard indeed hasn't been declared. You need to either move the definition of printBoard before getMove (with the definition available, it is also declared) or add at least a declaration
void printBoard(char [][ArrSize]);
outside the class (also before you use it anywhere). In addition, your code does not compile because there is at least one typo (upper case, lower case makeBoard), the definition of makeBoard is missing and the closing brace of getMove is missing. Also, maybe you want to call printBoard with TTTarray instead of 0?
PS: Please post code with proper indentation next time. It is really hard to check whether parentheses balance like this...
My problem is in the following C++ code. On the line with the 'cout' I get the error:
"'number' was not declared in this scope".
.h
using namespace std;
class a{
int number();
};
.cpp
using namespace std;
#include <iostream>
#include "header.h"
int main(){
cout << "Your number is: " << number() << endl;
return 0;
}
number(){
int x = 1;
return x;
}
Note: I'm aware this isn't the cleanest code. I just wanted to get the function working and refresh my memory on how to use headers.
For minimal fix, three basic changes are necessary.
Proper implementation of the number() method
int a::number() {
int x = 1;
return x;
}
Proper invocation of the number() method
a aObject;
cout << "Your number is: " << aObject.number() << endl;
There are many other enhancements possible though.
Addition, as pointed out by #CPlusPlus, usable scope of number() method, for example declaring it public
class a{
public:
int number();
};
Try this in your cpp file
using namespace std;
#include <iostream>
#include "header.h"
void a::number()
{
int x = 1;
return x;
}
int main()
{
cout << "Your number is: " << a().number() << endl;
return 0;
}
As for your header file replace class with a struct. The reason you are getting this error is because the compiler cant find the variable number. It is actually a method of a class.The reason you are replacing the class with a struct is because by default everything in a struct is public. So your header file called header.h should look like this
using namespace std;
struct a
{
int number();
};
There are three issues with your code.
The definition of the function number().
As you declared, it is a member function of the class "a". In your .cpp, the class name should be used as a prefix to the function. I mean,
a::number(){
int x = 1;
return x;
}
As the function is a member of the class "a", there are only two ways of accessing it,
If the function is a static function in the class, you can access it with :: operator. Like a::number().
If the function is not a static function, that is true in your case, you should instantiate the object out of the class "a" and they use "." operator with the reference. I mean,
a obj;
obj.number().
Your function number() is declared in private scope. You may recall that by default the scope is a class is private unless you specify public or protected. So the private function number() cannot be used outside the declared class unless there is a friend to it.
Below the code that I fixed,
.h
using namespace std;
class a{
public:
int number();
};
.cpp
using namespace std;
#include <iostream>
#include "header.h"
a::number(){
int x = 1;
return x;
}
int main(){
a obj;
cout << "Your number is: " << obj.number() << endl;
return 0;
}
This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 9 years ago.
#include <iostream>
namespace oo{
class A{
public:
template<typename T>
static T get_value(){return static_cast<T>(55);}
};
template <typename T=A>
class B{
public:
static double f(){return T::get_value<double>();}
};
}
int main(int argc, char *argv[])
{
using std::cout;
using std::endl;
cout << oo::B<oo::A>::f() << endl;
return 0;
}
Considering the example up here, it compiles with an error "type name is not allowed" which refers to "double" and arguments in "get_value()".
Someone has righted this wrong by rewriting the function f() as followed:
static double f(){return T::template get_value<double>(); }
Yet, I do not quite understand the use of "template" here. Could anyone explain that to me, please?
Thanks in advance for your comments.
The reason is how the compiler interpret that line, when you use templates, the syntax has more than one possible interpretation, take a look to the following :
static double f()
{
return T::get_value < double > ();
}
in your function, how you now that the T parameter passed to the B class has a function named get_value or a data member named get_value ? If the case is the second then you are using the operator lees-than between that member and double, and then between double and (). Well the first assumption of the compiler is these option, if you wat to tell him that this is a function with template (for the correct interpretation of "<") you need to put the keyword template
this is what's going on at runtime.
namespace oo{
class A{
public:
// template<typename T> // T replaced with <double> type.
static double get_value(){return static_cast<double>(55);}
};
//template <typename T=A> // T replaced with <oo::A> type.
class B{
public:
static double f(){return oo::A::get_value/*<double>*/();}
};
}
int main(int argc, char *argv[])
{
using std::cout;
using std::endl;
cout << oo::B::f() << endl;
return 0;
}
this line :
static double f(){return T::get_value();}
is correct and usually will be compiled without any errors(depend on witch compiler you're using), because the template declaration will be valid for the next scope.
template <class T>
class foo
{
//T will be valid in this scope.
};
this is not the case to implement template classes/functions, you usually want to do that in cases where you want to prevent the using of multiple overloading.