Yet another Scrabble project question... This is a simple one.
It seems I am having trouble getting my global constants recognized:
My board.h:
http://pastebin.com/7a5Uyvb8
Errors returned:
1>C:\Users\Francisco\Documents\FEUP\1A2S\PROG\projecto3\projecto3\Board.h(34): error: variable "TOTAL_ROWS" is not a type name
1> vector< vector<Cell> > _matrix(TOTAL_ROWS , vector<Cell>(TOTAL_COLUMNS));
1>
1>main.cpp
1>compilation aborted for .\Game.cpp (code 2)
1>Board.cpp
1>.\Board.h(34): error: variable "TOTAL_ROWS" is not a type name
1> vector< vector<Cell> > _matrix(TOTAL_ROWS , vector<Cell>(TOTAL_COLUMNS));
1> ^
1>
Why does this happen? Why is the compiler expecting types?
Thanks for your time!
EDIT:
Disregard my previous edit...
This is my default constructor:
Board::Board()
{
_matrix(TOTAL_ROWS, vector(TOTAL_COLUMNS));
}
I get the following error.
1>.\Board.cpp(16): error: call of an object of a class type without appropriate operator() or conversion functions to pointer-to-function type
1> _matrix(TOTAL_ROWS, vector<Cell>(TOTAL_COLUMNS));
1> ^
Why does this happen?
I managed to solve all the problems with my file. I used
Board::Board() :
_matrix(TOTAL_ROWS, vector<Cell>(TOTAL_COLUMNS))
{}
instead. Thanks for all your help!
The way that is written, you are defining a function called _matrix that returns a vector. So TOTAL_ROWS is expected to be a type name, since it is being parsed as a paramter type. I assume what you are trying to do is define a variable called _matrix that is a vector.
What you want to do is leave off the constructor, and initialize the variable inside your constructor. Only constant integral values can be initialized in the body of the class, at least in the current version of the standard.
Leaving off the unimportant parts:
Board() : _matrix(TOTAL_ROWS, vector<Cell>(TOTAL_COLUMNS)) { }
private:
vector< vector<Cell> > _matrix;
Note that this is just an example. Presumably you have an implementation file with an actual body for Board(), and you should put the initialization there rather than directly in the header or you'll get errors. The important thing is that you should not do it when you declare _matrix initially.
For your new question, extern const unsigned int TOTAL_COLUMNS = 15; defines TOTAL_COLUMNS every time Board.h is included by a file. Constant variables at namespace scope have internal linkage by default, so if you leave off the extern you will be okay.
In general, if the variable isn't constant, you take an approach similar to the one for _matrix. You leave off the initialization in the header, and then inside an implemenation file put it back on:
board.h:
extern const int TOTAL_COLUMNS;
board.cpp:
extern const int TOTAL_COLUMNS = 15;
You try to initialize the vector on it's definition, which is not the correct way to do this for object variables, the correct way is this:
extern const unsigned int TOTAL_ROWS = 15;
extern const unsigned int TOTAL_COLUMNS = 15;
class Board
{
public:
Board() : _matrix(TOTAL_ROWS, vector<Cell>(TOTAL_COLUMNS)) {}
private:
vector< vector<Cell> > _matrix;
};
In your header file, I see:
private:
vector< vector<Cell> > _matrix(TOTAL_ROWS , vector<Cell>(TOTAL_COLUMNS));
This seems to be declaring a private member variable, _matrix, and is apparently an effort to call the constructor for _matrix at the same time. You cannot call the constructor in this way.
Remember that your header file may be included in MANY program files.
As a result, headers should not contain execution instructions (certain exceptions exist, such as inline methods and templates). You never know where the header will be included, so you never know where the code in a headerfile will appear.
It is good advice to write your header files so that they are safe to be included anywhere.
If you want to continue this code, I suggest:
The constructor of Board() should construct the member variable explicitly:
Board::Board() :
_matrix(TOTAL_ROWS, .....);
// This will call the matrix constructor ONLY when the Board constructor is called.
{
}
Then the Board constructor should be called, but ONLY in a .cpp file, not in a .h file.
This is my default constructor:
Board::Board() { _matrix(TOTAL_ROWS,
vector(TOTAL_COLUMNS)); }
I get the following error. [ .... ]
You did not follow the examples and syntax provided by #Dennis Zickefoose, #KillianDS, and myself.
Please re-read our answers and study our code.
You can't call a constructor in the header file (or any code for that matter).
Related
can someone please give me a hint how to solve the following problem:
clang++-7 -pthread -std=c++17 -o main createLibrary/configuration.cpp createLibrary/growbox.cpp createLibrary/helper.cpp createLibrary/httprequests.cpp main.cpp
In file included from createLibrary/configuration.cpp:2:
In file included from createLibrary/configuration.h:1:
In file included from createLibrary/growbox.h:12:
createLibrary/httprequests.h:13:10: error: fields must have a constant size:
'variable length array in structure' extension will never be supported
char device[configuration::maxNameSize];
^
1 error generated.
I'm including the .h files in the order configuration.h, httprequests.h. I want all necessary config-parameters to be configured in the configuration.cpp file, but I got the displayed error. What am I doing wrong here?
configuration.h
extern int const maxNameSize;
configuration.cpp
int const configuration::maxNameSize = 30;
httprequests.h
char device[configuration::maxNameSize];
httprequests.cpp
char HTTPREQUESTS::device[configuration::maxNameSize];
An extern const int is not a constant expression.
a variable is usable in constant expressions at a point P if
the variable is
a constexpr variable, or
it is a constant-initialized variable
of reference type or
of const-qualified integral or enumeration type
and the definition of the variable is reachable from P
and
P is in the same translation unit as the definition of the variable
(emphasis added)
I want all necessary config-parameters to be configured in the
configuration.cpp file
You are out of luck. The value of maxNameSize must be visible to it's compile-time users.
Declare maxNameSize like this
// configuration.h
class configuration
{
public:
static const int maxNameSize = 30;
...
};
And no need to define it in configuration.cpp.
Your way doesn't make maxNamesize a compile time constant.
EDIT, I am assuming that configuration is a class. If it's a namespace then do the following instead
// configuration.h
namespace configuration
{
const int maxNamesize = 30;
...
}
Constants are an exception to the one definition rule, so it's OK to define them in a header file.
What am I doing wrong here?
You have defined an array variable with size that is not compile time constant.
Solution: You can either
Define the variable in the same translation unit where you use it as the size of an array so that it may be compile time constant. Given that the array is in a header, which presumably is included into multiple translation units, the size cannot be defined externally. It has to be either static or inline.
Or use a dynamic array instead. Simplest way to create dynamic array is to use std::vector.
The following sketch to fails to compile in the Arduino environment.
Given that typedefs can be used within Arduino software, is Automatic Prototype Generation the underlying mechanism that causes the failure? If so, what is it and why isn't Arduino providing a lightweight wrapper around C++?
#define PRODUCE_WACKY_COMPILETIME_ERROR
typedef int MyMeaningfulType;
#ifndef PRODUCE_WACKY_COMPILETIME_ERROR
void myFunc(MyMeaningfulType myParam);
#endif
void myFunc(MyMeaningfulType myParam)
{
myFunc(10);
}
void setup() {}
void loop() {}
For the benefit of the search engines, the errors reported are:
error: variable or field 'myFunc' declared void
error: 'MyMeaningfulType' was not declared in this scope
Please refer to http://arduino.cc/en/Hacking/BuildProcess the specific quote is:
This means that if you want to use a custom type as a function argument, you should declare it within a separate header file.
This page does a good job of explaining how the Arduino Language is different from C/C++ in how it works/pre-processes files.
They are attempting to create prototypes for every function they find. Unfortunately, if you define a typedef in the file before the function, and use that in a function definition, the place they put the function prototype does not see it, and this generates a syntax error.
If you use the 'struct * ' syntax instead in those function definitions, you benefit from C's 'opaque type' facility, in which you can use a struct definition without having it be declared beforehand. So, build the typedef, use it, but use the struct definition in any functions that use the typedef in arguments.
typedef struct mytype_ {
int f1;
} mytype_t;
void myfunc(struct mytype_ * xxx) {
xxx->f1 = 1;
}
Noob question, but would like to understand the following:
Imagine I have a multifile project. I'm specifying a class in a header file to be shared among all the files in the project, and I write this : static int test = 0; and in the next line this: static const int MAX = 4;
The first one would be an error trying to compile because of the one definition rule. But the second one will compile without errors. Why?
From what I understand, both have the same properties: whole execution storage duration, class scope and no linkage.
Any help?
EDIT: testing an external constant declaration in a header: extern const int MAX = 4; to force external linkage produced the expected error. So I don't understand why with the variable it gives me the error and with the constant it doesn't.
Try
static const int test = 0;
I've sometimes noticed compiler errors with the immediate initialization of static const variables in the header file. You can always use the declaration in the header
class MyClass
{
// ...
static const int test;
// ...
}
and initialize it in the corresponding .cpp file
const int MyClass::test = 0;
This should work properly with any other types than int as well.
Integer constants in C++ don't actually occupy any space in the object and don't act like variables in general. Think about them more like numbers that are given names in this particular context.
I got a global object of type "unnamed-struct" and i'm trying to define it. I don't want to pollute my global namespace with such useless type (it will be used only once).
Global.h
extern struct {
int x;
} A;
Is there any correct way to define such object?
I was trying this:
Global.cpp
struct {
int x;
} A = { 0 };
But VS2012 throws "error C2371: 'A' : redefinition; different basic types". Thanks.
One possible solution: create another file Global_A.cpp that does not include Global.h, and define A there. By the equivalent-definition rule this will be valid, as long as the anonymous struct definitions are equivalent.
This is still a bad idea, and most compilers will warn about it e.g. (gcc): warning: non-local variable `<anonymous struct> A' uses anonymous type.
There is no way to do just this simply because it would be error prone: some time in the future someone (probably even you) may want to modify this structure's definition and he might forget to do this in the header and source files accordingly. So you will have to invent a name for this structure and use its name the source file and leave its definition up to the header.
I don't know if this helps you, and this my first post... So take it easy.
I just ran into this issue and what I did was I added a function that manipulates the struct to the file that contained the anonymous struct. That way I can call that function from any file in my project, and it manipulates the values in the struct for me.
Here is an example:
header.c has this anonymous struct:
struct
{
char line1[80];
char line2[80];
char line3[80];
} header;
I want to manipulate those values in "interface.c" because I am making a command line interface in another file. My first instinct was to use an extern, but it seems like adding the following function to header.c is just as good or better (Some people discourage the use of externs when avoidable).
void changeHeaders(char *one, char *two, char *three);
void changeHeaders(char *one, char *two, char *three)
{
strcpy(header.line1, one);
printf("\nHeader 1: %s", header.line1);
strcpy(header.line2, two);
printf("\nHeader 2: %s", header.line2);
strcpy(header.line3, three);
printf("\nHeader 3: %s", header.line3);
}
Now as long as I include the prototype for that function I can manipulate those struct variables from any file by using that function. Hope that helps someone.
I have a file called Student.h which have the static integers in this way:
class Student
{
public:
static int _avrA,_avrB,_avrC,_avrD;
};
and I have university.h that inherits Student.h .
On the implementation of University.cpp , one of the functions returns:
return (_grade_average*(Student::_avrA/Student::_avrB))+7;
and the compiler writes:
undefined reference to Student::_avrA.
Do you know why it happens?
You have declared those variables, but you haven't defined them. So you've told the compiler "Somewhere I'm going to have a variable with this name, so when I use that name, don't wig out about undefined variables until you've looked everywhere for its definition."1
In a .cpp file, add the definitions:
int Student::_avrA; // _avrA is now 0*
int Student::_avrB = 1; // _avrB is now 1
int Student::_avrC = 0; // _avrC is now 0
int Student::_avrD = 2; // _avrD is now 2
Don't do this in a .h file because if you include it twice in two different .cpp files, you'll get multiple definition errors because the linker will see more than one file trying to create a variable named Student::_avrA, Student::_avbB, etc. and according to the One Definition to Rule Them All rule, that's illegal.
1 Much like a function prototype. In your code, it's as if you have a function prototype but no body.
* Because "Static integer members of classes are guaranteed to be initialised to zero in the absence of an explicit initialiser." (TonyK)
You have to define the static data members as well as declaring them. In your implementation Student.cpp, add the following definitions:
int Student::_avrA;
int Student::_avrB;
int Student::_avrC;
int Student::_avrD;