I had made an structure for feature tracks:
struct FeatureTracks{
std::vector<std::vector<cv::Point2f> > tracks;
std::vector<size_t> offset;
};
Then making a function to call it:
void genTrackMatrix(const std::vector<cv::Mat>& images, FeatureTracks& trackMatrix, int tWindow, int stride);
But the function calling is giving an error:unknown type name 'FeatureTracks'
Please help me out. Thanks in advance.
Well, I assume, that it is simply not defined. The struct definition must be done before the function prototype declaration. Is the struct defined within another c file? Then move it to a header file and include the Header. Is the struct definition later in the c file? Then move it to the beginning.
The C-Compiler has no global scope, it only sees the current file and processes it top-down. Just "play" being a compiler and step through the C-file. Have you seen every type definition before it is used?
Related
I am relatively new to C++, coming from a Python background.
I have the following header file:
struct Example
{
int n_example;
float random_number;
float second_random_number;
Example(int n_example, float random_number, float second_random_number);
};
I do not get what the second to last line do (i.e, Example(int n_example, float random_number, float second_random_number); )
Might be a super silly question, but it is the first time that I encounter such syntax in C++.
Indeed, normally for struct definition I am used to something like:
struct Example
{
int n_example;
float randon_number;
float second_random_number;
};
this here
Example(int n_example, float random_number, float second_randon_number);
is the declaration of the constructor, you can call that and pass the parameters every time you want to construct a new instance of the class Example...
like
int main()
{
Example foo(0, 3.14f, 2.77f);
}
the only thing you are missing is the implementation of that constructor...
it may look like this (depending on what version of c++ you are using):
Example(int n_example, float random_number, float second_random_number) :
n_example{n_example},
random_number{random_number},
second_random_number{second_random_number},
{
...
}
The line you're questioning is a class constructor and as far as I'm aware is something equivalent to __init__ in Python. The reason it's declared in the class definition body - between {} - is because C++ is strongly typed, which means that the class definitions has to be fully specified. You cannot "add" new functionality afterwards, during a runtime of a program. Contrary to C++, Python belongs to loosely typed group of languages where you can define classes' fields and methods on the go during a runtime which makes it more flexible but more error-prone in the end.
Also be aware that this is just a simple declaration which should be included within the header file .h The definition of this constructor most of the time (unless inlined) will end up in respective .cpp file which consist of all the logic related to the class. This separation of declaration .h and definition .cpp files is one of the building blocks of the language. In the end only the .cpp files are compiled and then linked together resulting in a hopefully working application.
I'm learning C++ using Xcode and have written several small programs including a hangman game but I'm having trouble every time I try to separate a class into definition and implementation. I made a simple case that shows my problem. Short version is it seems that I need to specify a type in the implementation file even though it is already defined in the header file. I get "C++ requires a type specifier for all declarations" on lines 12 and 13 in my example. But if I change line 12, for example, to
int xmlelem::atrb_count = 0;
it gets the error "non-static data member defined out-of-line". In other cases I have got an error saying that I was trying to redefine something. I think I'm missing a fundamental concept somewhere. I did not see this particular issue in the handful of similar questions I looked at.
xmlelem.hpp
// xmlelem.hpp
// learn header
//
//
#ifndef xmlelem_hpp
#define xmlelem_hpp
#include <stdio.h>
#include <string>
#endif /* xmlelem_hpp */
class xmlelem {
private:
int atrb_count;
std::string tag_name;
public:
xmlelem(std::string tag);
void add_atrib();
std::string output();
};
xmlelem.cpp
// xmlelem.cpp
// learn header
//.
//
#include "xmlelem.hpp"
#include "string"
#include <iostream>
// line 11
xmlelem::atrb_count = 0;
xmlelem::tag_name = "";
xmlelem::xmlelem(std::string tag){
tag_name = tag;
}
void xmlelem::add_atrib(){
atrb_count++;
}
std::string xmlelem::output(){
std::string build = "<";
build = build + tag_name + " " + std::to_string(atrb_count);
build = build + ">";
return build;
}
and main.cpp
// main.cpp
// learn header
//
//
#include <iostream>
#include "xmlelem.hpp"
using namespace std;
int main(){
xmlelem clip("test)");
std::cout << clip.output() << " test \n";
}
Let's take a look at the (second) error message.
non-static data member defined out-of-line
There are two parts to the error: "non-static data member" and "defined out-of-line". These are incompatible, so one of them must be changed. Furthermore, only one of them should be changed, or else you may run into a different problem. Decide which of the two parts is correct for your situation.
Keep "defined out-of-line"
When the line
int xmlelem::atrb_count = 0;
is encountered at namespace scope (that is, in neither a function nor a class/struct/union definition), it is an out-of-line definition. This definition tells the compiler to reserve, right at that spot, enough space for an int. Then whenever any xmlelem object accesses the atrb_count member, it will access this particular space. So there is one int shared by all objects.
However, this behavior corresponds to a static member. To make the declaration agree with the implementation, the keyword static needs to be added.
class xmlelem {
private:
static int atrb_count;
/* rest of the class definition */
};
Keep "non-static"
A non-static data member is stored inside each object of the class. Each object can do what it wants with its copy of the data without impacting other objects. So telling the compiler to reserve space outside the objects is contradictory. Simply removing the out-of-line definition is enough to get rid of the error message, but presumably you wanted that initialization to occur somewhere, right?
The initialization of non-static data members can be done either in-line or in a constructor. An example of moving the initialization in-line is the following.
class xmlelem {
private:
int atrb_count = 0;
/* rest of the class definition */
};
This is sometimes reasonable, but the stated goal was to separate the interface from the implementation. Therefore, it might be undesirable for the initial value of 0 to appear in the header file, as it does in the above. The alternative is to move the initial value to the constructor (to each constructor, if you had more than one).
xmlelem::xmlelem(std::string tag) :
atrb_count(0),
tag_name(tag)
{
}
(I've also taken the liberty of moving the initialization of tag_name into the initialization list.)
Remember, if you have more than one constructor, this needs to be done in each constructor that actually utilizes the default value (for an exception, think "copy constructor"). Repeated code is a drawback; it is up to you to decide if the gains are worth the cost.
Remember that you are declaring a class. A class is an abstract concept. When you do this xlemem::atrb_count = 0;, you are having a concrete value on an abstract concept. Doesn't make sense, right? You don't think of a particular color when you think of the general concept of dog. Any initiliazations should be done inside the constructor, because only in the constructor is that we create a concrete object.
Therefore, you should eliminate lines 11 and 12 where you initialize these 2 attributes and your constructor code should be changed to:
xmlelem::xmlelem(std::string tag){
tag_name = tag;
atrb_count = 0;
}
Note that it isn't necessary to initialize a string to "".
I just started learning more of c++ and am writing a small rendering engine as an example case study. As i started to implement more code I got annoyed by typing types like
std::vector<std::vector<int>>
over and over again. As most of you know already, this get's infinitely worse if you are looping over said vector
for (std::vector<std::vector<Tile>>::const_iterator layerRow = ...) {}
Since this is not just annoying but also very error prone, I looked into using typedefs and soon changed those into alias', following Scott Meyers advice in "More effective C++".
I got one problem now which I can't seem to wrap my head around. Given the following two files (corresponding header and source file):
map.h:
class Map
{
public:
using tileLayerVector_t = std::vector<std::vector<Tile>>;
using rawDataLayerVector_t = std::vector<std::vector<int>>;
tileLayerVector_t getTileLayer(const std::string pLayerName) const;
void generateTileMapLayer(const std::string pMapLayerName, const rawDataLayerVector_t pRawMapData, const std::shared_ptr<Texture> pTexture);
}
map.cpp:
#include <map.h>
tileLayerVector_t Map::getTileLayer(const std::string pLayerName) const
{
return mapLayers.at(pLayerName);
}
void Map::generateTileMapLayer(const std::string pMapLayerName, const
rawDataLayerVector_t pRawMapData, const std::shared_ptr<Texture> pTexture)
{
int tileCount = 0;
int xPos = 0;
int yPos = 0;
...
std::pair<std::string, tileLayerVector_t> tileLayer(pMapLayerName, tileMapLayer);
mapLayers.insert(tileLayer);
}
Function generateTileMapLayer() compiles fine without a problem. As soon as I implement getTileLayer() the UI is giving me an error "identifier 'tileLayerVector_t' is undefined" and the compiler is giving me some weird error about a missing ";" somewhere. This compiler error vanishes if I put getTileLayer() in comments.
I don't understand why I can use the alias within the function generateTileMapLayer() as a type definition for the hash map, but cannot use it as a return type for getTileLayer(). I put Map::tileLayerVector_t as a return type and it works. Why does it work without the namespace within generateTileMapLayer() though?
Maybe someone can help me with this. Thank you in advance!
A class defines a scope. How you access something in a given scope depends on whether you are writing code that's inside or outside that scope.
So when you make the declaration using tileLayerVector_t = ...; within class Map you are providing an alias for a new type Map::tileLayerVector.
This is why your code inside the class can use the type without qualification, but code outside cannot.
You could move your using-declarations outside the class, but that would pollute the global namespace. A better solution, I think, would be to simply qualify the types where needed:
Map::tileLayerVector_t Map::getTileLayer(...) // must qualify type here
{
tileLayerVector_t temp = ...; // inside a class method, no problem here
}
A more modern solution would be to use "type inference". I believe you need at least a C++11 compliant compiler to take advantage of this feature. My understanding is that the trailing return type allows the compiler to defer establishing the actual type until after the function signature has been generated, at which point the scope has been established.
auto Map::getTileLayer(...) -> tileLayerVector_t
{
....
}
I am trying to initialize a deque with pointers to a user defined struct, Tile, in order to eliminate unnecessary copying.
My code looks like this:
Tile *start = new Tile(0,0,0, 'q', nullptr);
deque<Tile*> search();
search.push_front(start);
The above code is located in main.cpp.
The Tile struct looks like this, and is contained in hunt.h:
struct Tile
{
int row; int col; int farm;
char tile;
Tile * added_me;
Tile(int f, int r, int c, char t, Tile * a) :
farm(f), row(r), col(c), tile(t), added_me(a){}
};
The layout of my program is as follows:
main.cpp: includes "io.h"
io.h: includes "hunt.h", various standard libraries
hunt.h: includes vector, deque, Tile struct
However, I am getting an error in main.cpp when I try to push_front(start): expression must have class type." I wasn't sure if a possible fault in my #includes was causing this error, so please let me know if this is the case. Otherwise, I am not entirely sure how to fix this error.
Thanks in advance!
When you write
deque<Tile*> search();
you aren't actually declaring a deque<Tile*> named search and using the default constructor. Instead, C++ interprets this as a function declaration for a function named search that takes no parameters and returns a deque<Tile*>. You can't call push_front on a function, hence the error.
To fix this, either remove the () from the declaration of the variable, or replace them with {} (if you're using a C++11-compliant compiler). That will cause C++ to (correctly) interpret that you want to declare a variable.
Hope this helps!
I'm having a little problem trying to use my "gameAux" class in "userAux.hpp" file I made.
Here are the two hpp files I made.
I marked the place where I get an error.
userAux.hpp:
#include "gameAux.hpp"
class userAux{
int gameId;
int userId;
int rate;
gameAux aGame; <---error: ‘gameAux’ does not name a type
};
gameAux.hpp:
#include "userAux.hpp"
class gameAux{
int gameId;
userAux aUser; <--- OK
};
I'll be very happy if someone could point out what's the problem :)
You cannot have one class include an instance of another class, and have that other class include an instance of the first class. That's an infinite recursion and obviously cannot work.
The answer is to use pointers and forward declarations.
class gameAux; // forward declaration
class userAux{
int gameId;
int userId;
int rate;
gameAux* aGame;
};
class gameAux{
int gameId;
userAux* aUser;
};
When two classes depend on each other like this I would be tempted to place them both in the same header file. However if you want separate header files then you could forward declare each class in the other classes header file. That way neither header file needs to include the other.
Your problem is that both of your classes depend on each other. When the compiler goes to see how much space it needs to reserve for gameAux objects, it says 'ok, I need an int and a userAux to fit in there'. So the next question is, how much space does it need for ints and userAux objects?
Then when it tries to figure out how much space it needs for a userAux object, it says 'ok, three ints and a gameAux object'... and there's the problem. It's going to keep going back and forth between those two files, trying to figure out how much space it needs for each thing, and never be able to figure it out.
To solve this, you need to make one of your classes depend on a reference or pointer to the other class. Since references and pointers always take up the same amount of space on a given system, the compiler will be able to allocate space for a userAux if it sees this:
class gameAux;
class userAux{
int gameId;
int userId;
int rate;
gameAux &aGame; // or gameAux *aGame; // <---error: ‘gameAux’ does not name a type
};
and then it will have a fine time allocating space for both of the objects, no problems ^^
EDIT: Also, you won't need to #include the header file for gameAux any more at the top of userAux.hpp - just forward-declare gameAux like so at the top of the file: class gameAux.
You don't need to include the entire class definition. You can avoid a circular dependency by just forward declaring, and using a pointer:
#include "gameAux.hpp"
class gameAux; // forward declaration
class userAux{
int gameId;
int userId;
int rate;
gameAux *aGame;
};
and vice versa in the other file. Then #include the appropriate hpp header in the implementation source file for each class.