C++ header functions - c++

Sorry for asking a beginners question. I'm quiet familiar with Java, C# ...
but I have to write an OpenGL Program in C++ and there is something I don't understand:
I have to parse a text file to get vertices and put them into a vector. So I wrote a method that receives my vector of Vertex objects.
It works when I define the method before I call it
std::vector<AESParser::Vertex> vertices;
void parseVertices(std::vector<AESParser::Vertex> &verts){
...
}
...
parseVertices(vertices);
But fails when doing it the other way around. So I understand I have to declare it in the header file. So I wrote something like this:
*** Header ***
class AESParser
{
public:
struct Vertex{
float x;
float y;
float z;
};
AESParser();
virtual ~AESParser();
void read();
protected:
private:
int readNumVertices(std::fstream &stream);
int readNumFaces(std::fstream &stream);
void parseVertices(std::vector<Vertex> &verts);
Vertex readVertex(std::fstream &stream);
};
I know there are probably many more mistakes since I never did C++ but the main problem with this is, that I get the following error message:
undefined reference to `AESParser::parseVertices(std::vector<AESParser::Vertex, std::allocator<AESParser::Vertex> >&)'
So something seems to be wrong with the "parseVertices()" method and I don't see what. It works for the others like "readNumVertices()".
Thanks for your help!

Your function belongs to the AESParser class, so you need to define it as such
void AESParser::parseVertices(std::vector<AESParser::Vertex> &verts){
...
}
When you have the function definition written as
void parseVertices(std::vector<AESParser::Vertex> &verts)
Then it is a free function (doesn't belong to a class) that happens to have the same name, return the same type, and take the same arguments. But it is a different function.
Note in the first version, there is a AESParser:: scope appended to the front of the function name.

Related

Can you define C++ methods in a reopened class environment, rather than by prefixing with the class name?

In every lesson and book on C++ I've ever seen, a class has been written like this:
header.h
class MyClass
{
...
int myMethod(int my_para);
};
source.cpp
...
int
MyClass::myMethod(int my_para)
{
...
}
But I do find that the MyClass:: just adds to the natural chaos and bewilderment of C++, especially when MyClass is actually more like MySomethingSomethingCreator. I would like to write my class definitions in more of a namespace style, like this:
header.h
class MyClass
{
...
int myMethod(int my_para);
};
source.cpp
class MyClass
{
...
int myMethod(int my_para)
{
...
}
}
Now, I know from trying that doing exactly this does not work, but is there a way to do something similar - just to remove a little of the noise? I am not interested in defining functions actually inside the class declaration - that's the work of the devil!
but is there a way to do something similar
No.
MyClass:: just adds to the natural chaos and bewilderment of C++
It's just one of the little things that a new C++ programmer has to learn to accept. Once you get used to it, it will no longer be bewildering.
MyClass:: just adds to the natural chaos and bewilderment of C++
I wouldn't agree with you. Imagine you are working with a huge code database, and you come across a definition of a function in .cpp file like this.
.
.
.
.
int myfunc(std::string some_arg)
{
//whatever can be here
}
.
.
.
.
.
And now you would wonder, is this a function in a namespace or method of some class. Of course the class specifier you suggested would appear above, but in can be thousand of lines above, or even 10 thousands, which one probably wouldn't want to deal with. Someone would like to know if it is a method or function by directly looking on it.
The MyClass:: specifier serves greatly for this purpose.
You cannot. This is generally not a problem, though. In fact, there is good reason to want to do this with free functions. John Lakos points out in Large-Scale C++ Volume I (2020) p. 155–156, you can (and may want to) do this:
// foo.h
namespace my_product {
int foo(int);
} // namespace my_product
then
// foo.cpp
#include <my_product/foo.h>
int my_product::foo(int x) {
return x * 2;
}
The advantage of this is: suppose you want to change the signature to take float and you change it in the .cpp to float my_product::foo(float x). If done this way, float my_product::foo(float x) can only define the function, it can't declare it, so you'd get a compile error: https://godbolt.org/z/eGbv3rTx5
error: out-of-line definition of 'foo' does not match any declaration in namespace 'my_product'
float my_product::foo(float x) {
^~~
whereas if your .cpp file is
// foo.cpp
#include <my_product/foo.h>
namespace my_product {
float foo(float x) {
return x * 2;
}
} // namespace my_product
and you try to use the function, you have to wait for the whole project to build and then get a link error: https://godbolt.org/z/soo7r97fG
undefined reference to `my_product::foo(int)'
I've started to get in this habit of defining functions like this so I can have immediate compile errors rather than waiting for a potentially big build only to get a link error, which then requires fixing the header (hopefully correctly!) and then waiting again for a big rebuild.

c++ Error when Testing library

I am creating an Arduino library which takes two constructors for a personal project of mine, but for some reason I keep getting an error which is specific to types, first let me show you how the structure goes. so here is my files:
this is the header file:
#ifndef iGA_H
#define iGA_H
class iGA {
public:
getParameters(int soundA[], int soundB[], int parentId[]);
private:
int _soundA[];
int _soundB[];
int _parentId[];
}
the cpp file:
#include <iGA.h>
iGA::getParameters(int soundA[], int soundB[], int parentId[])
{
_soundA = soundA;
_soundB = soundB;
_parentId = parentId;
}
And this is how im pretty much calling the constructor in the sketch, within the setup() function:
#include <iGA>
iGA iga;
void setup() {
iga.getParameters(r, r1 , r2);
}
and here is the error:
In file included from /home/bargros/Dropbox/iGA__NewBild/iGA__NewBild.ino:34:0:/home/bargros/Arduino/libraries/iGA/iGA.h:10:58: error: ISO C++ forbids declaration of 'getParameters' with no type [-fpermissive]getParameters(int soundA[], int soundB[], int parentId[]);
I know the error has something to do with argument types or maybe im calling the constructor wrongly but I also tried calling it like this:
iGA iga = getParameters(etc,etc,etc);
im relatively new to c++ and im a little clueless as to what this error is telling me. Does anyone have any sort of idea of why this happens?
I believe two issues:
Issue 1: Your function should return something right? you may want to set it as void if it just meant to assign the parameters to the private members (it is a setter and not a get in your case). Add void in the proper locations both inside the class and when you write its definition.
Issue 2: I think that you can't send an array[] as a parameter. And I assume that you already know the size. You need, instead, to send a pointer that points to the first element of the array along with the size of the whole array. Then, once you receive the parameters, for every private member, you create a new array with the size received (or just fill the private member directly) and fill the values by iterating the received array using the pointer received.
Edit: I just checked and passing int array[] should be fine. So fixing issue one will fix your problem. See here for further documentation.
In C++ you have to be explicit that a function doesn't return anything, which you do by saying it returns void:
getParameters(int soundA[], int soundB[], int parentId[]);
needs to be
void getParameters(int soundA[], int soundB[], int parentId[]);
and
iGA::getParameters(int soundA[], int soundB[], int parentId[])
needs to be
void iGA::getParameters(int soundA[], int soundB[], int parentId[])

Passing function pointer with scope resolution operator arduino

I'm a newbie to arduino and programming.
I've included a library inside my own library in arduino, but first library contains a function which has a pointer function as a parameter. It is an interrupt service routine(ISR) but I need to call a function in my cpp file when interrupt is occurred. So I need to pass the pointer of that function to the first library code. It works well when I use it in .ino file, I can pass it like,
attachInterrupt(functionISR_name);
but when I use it in .cpp file, I get errors. my function is like,
void velocity::functionISR_name(){
//some code
}
but how can I pass the pointer of this function to the first library function? I tried this way but got errors,
attachInterrupt(velocity::functionISR_name);
You cannot pass a method to a function which expects a function, unless you define it static.
write it static :
static void velocity::functionISR_name()
and
attachInterrupt(&velocity::functionISR_name);
Unfortunately the static method is not bound to a specific instance any more. You should use it only together with a singleton. On Arduino you should write the class like shown below in the code snipped:
class velocity
{
static velocity *pThisSingelton;
public:
velocity()
{
pThisSingelton=this;
}
static void functionISR_name()
{
pThisSingelton->CallWhatEverMethodYouNeeded();
// Do whatever needed.
}
// … Your methods
};
velocity *velocity::pThisSingelton;
velocity YourOneAndOnlyInstanceOfThisClass;
void setup()
{
attachInterrupt(&velocity::functionISR_name);
// …other stuff…
}
This looks ugly, but in my opinion it is totally okay with Arduino as the opportunities are very limited on such a system.
Thinking again over it, I would personal go for the approach Sorin mentioned in his answer above. That would be more like that:
class velocity
{
public:
velocity()
{
}
static void functionISR_name()
{
// Do whatever needed.
}
// … Your methods
};
velocity YourOneAndOnlyInstanceOfThisClass;
void functionISR_name_delegation()
{
YourOneAndOnlyInstanceOfThisClass.functionISR_name();
}
void setup()
{
attachInterrupt(functionISR_name_delegation);
// …other stuff…
}
It would also save you some bytes for the pointer you need in the first example.
As a site note: For the future, please post the exact code (for e.g. attachInterrupt needs more parameter) and copy&paste the error messages. Usually error are exact at a place you do not suspect. This question was an exception. Normally I and other would ask for better specification.
You pass a pointer to the function but the function is a class member. Likely the call will be invalid because the this pointer will be garbage(may compile fine but will throw strange errors at runtime).
You need to define a plain vanilla function, outside of any class, and use that.
If you don't have a very complex project you can get away with having a global pointer to the class instance you should use and just delegate the call in your new function.
If you want to do thing the right way you need some mechanism to get the instance pointer I talked about above. Usually this involves either a singleton or some factory pattern.
Example:
class Foo {
void method() {
x = 5;
}
int x;
}
Having a callback on method will crash because you have an invalid pointer for this so x=5 will write 5 somewhere randomly in memory.
What you need is somehting like:
static Foo* foo_instance; // Initialized somewhere else.
void method_delegator() {
foo_instance->method();
}
Now you can pass method_delegator to the function. It will work because you now also pass foo_instance for this pointer.

Accessing a method of a member object in C++

I am trying to access a method of an object (myEOS.calc(...)) from a method of an object (myPlanet) of another class containing an instance of the first class (static EOS myEOS):
// class in class
class EOS {
public:
static float Y;
float calc(float);
};
float EOS::calc(float x){
return x; // some complicated calculation
}
class Planet {
public:
static EOS myEOS; // want only one instance; cf. below
static void setX(float* X); // must be static; cf. below
};
void Planet::setX(float* X) {
*X = myEOS.calc(*X); // will give an error
}
int main(){
Planet myPlanet;
}
This returns the linking-time error
In function `Planet::setX(float*)':
test.cpp:(.text+0x1a): undefined reference to `Planet::myEOS'
collect2: ld returned 1 exit status
Compiling separately, with -c, the classes and the main program (with an #include in the main file) gives no error; this looks like the key to the solution but I do not see the lock!
Does someone know what the problem is? I hope my intent is clear from what I have, even if there is some fundamental misconception. I thought I somewhat understood classes and reread tutorials but saw no discussion of classes within classes (not nested classes). I was not able to find a similar question on this site (from which I can usually get all the answers I need!) either.
By the way, following somebody else's question, adding explicit constructors (and correctly initialising the EOS in Planet's initialiser list) did not remove the compiler complaint about "undefined reference to Planet::myEOS'" (this done without thestatic` keyword).
Finally, note that Planet::setX needs to be static because a pointer to this method must have a "class-less" signature as it is passed to a function that cannot handle methods/classes:
void (*fun_ptr)(float*) = & (Planet::setX);
This also forces the object myEOS to be static (needs to be accessed from a static function), and anyway the initialisation of EOS objects is expensive.
Thanks a lot for anybody's help!
class Planet {
public:
static EOS myEOS; // want only one instance; cf. below
This code says "Compiler: Somewhere later will be a global EOS myEOS for this class. And the compiler says "ok", and does it's thing, waiting for you to tell it where the global EOS myEOS is.
Then the linker comes along to clean up the compiler's mess, and says "I can't find the myEOS, where'd you place the myEOS?" And displays an error.
You need to add the following lines to a CPP file somewhere:
float EOS::Y;
EOS Planet::myEOS;
Define the static variable.
// class in class
class EOS {
public:
static float Y;
float calc(float);
};
float EOS::calc(float x){
return x; // some complicated calculation
}
class Planet {
public:
static EOS myEOS; // want only one instance; cf. below
static void setX(float* X); // must be static; cf. below
};
void Planet::setX(float* X) {
*X = myEOS.calc(*X); // will give an error
}
// -------------------------
EOS Planet::myEOS;
float Planet::Y /* = <some value> if it makes sense*/;
// -------------------------
int main(){
Planet myPlanet;
}
See 9.4.2 Static Data Members in the standard (98).

Nested Classes C++ static inner methods (Xml parsing and trying to populate vector with values)

So this is what I am trying to accomplish. I am trying to use a sax parser to parse some XML. it looks like I need to call all their methods as statics. So if I want to pass a value back from say startElement it is static void startElement. Which brings me to my example code. I have been pulling my hair on how to update a value in a Nesting class from a static member function.
I have looked at several things such as defining OuterClass * oc; then trying to reference oc->allRecords, but since it is a static method inside, it fails. I am sure I am doing something wrong architecturally, so any feedback on what would be the right way to do this would be a great help. Thanks.
class Attribute {
string AttributeName;
string AttributeValue;
};
typedef shared_ptr<Attribute> AttributePtr;
class AttributeSet {
vector<AttributePtr> Attributes;
};
typedef shared_ptr<AttributeSet> AttributeSetPtr;
class OuterClass {
public :
vector<AttributeSetPtr> allRecords;
class InnerClass {
public:
static mymethod1() {
// I need to be able to set attributes here :
// This would be the characters method for sax parsing
// What is the right way to Attributes.push_back(new Attribute(Name,Value));
}
static mymethod2() {
// I also need to be able to add Records here :
// This would be the endElement for sax parsing
// What is the right way to allRecords.push_back(AttributeSet);
}
};
// EDIT: CALLING CODE GOES HERE (WAS EDITED - SEE BELOW)
};
// ADDING INFORMATION REGARDING HOW METHOD 1 & 2 are called
xmlSAXHandler saxHandler;
memset(&saxHandler, 0, sizeof(saxHandler));
saxHandler.initialized = XML_SAX2_MAGIC;
...
saxHandler.endElementsNs = &InnerClass::method2;
saxHandler.characters = &InnerClass::method1;
...
InnerClass innerXmlParsingClass
xmlSaxUserParseMemory( &saxHandler, &innerXmlParsingClass, xmlString, xmlString.length());
Your mistake is using an inner class (are you coming from Java?).
I don't know what you believe you are are achieving with an inner class, but it won't work. Don't use inner classes in C++ unless you really know what it does (for inner classes, protected and private members of the outer classes are seen as if they were public).
Now, as the solution to your problem, I guess it depends on the implementation you're using (I used once Apache's Xerces SAX, but I know Microsoft offers its own SAX implementation, and that there should be a lot other alternatives, so...)
Edit
After the comment, I found the following tutorial:
http://www.jamesh.id.au/articles/libxml-sax/libxml-sax.html
I must say that, coming from Java to C++, and using a C API, you have a kind of courage...
:-D
If you are not familiar enough with function pointers, and C in general, using libxml2 will be a challenge. Be sure that in the end, you will understand those notions... Note that C have a way to handle the data that C++, Java or C# developers associate to this. The C way is to pass a pointer to your data (the user data) to a function, and when the callback is called, it passes back this pointer, typed as a void *. You must then cast it back to its right type, and voilà, you have your this back.
:-)
Anyway, reading the doc, I see that when you parse the file, you'll call the following C function:
int xmlSAXUserParseFile( xmlSAXHandlerPtr sax,
void * user_data,
const char * filename);
the user_data part is the one that interest you because it enables you to have a context. So, wrapping this function in a C++ class, you could have something like:
// MySaxBase.hpp
class MySaxBase
{
public :
MySaxBase() ;
int parseFile(const std::string & p_filename) ;
virtual void startDocument() ;
virtual void endDocument() ;
private :
static void do_startDocument(void *p_user_data) ;
static void do_endDocument(void *p_user_data) ;
xmlSAXHandler m_sax ;
}
.
// MySaxBase.cpp
extern "C"
{
void do_startDocument(void *p_user_data)
{
// this static method will convert the p_user_data into
// the this pointer...
MySaxBase * saxBase = static_cast<MySaxBase *>(p_user_data) ;
// ...and call the right virtual method
saxBase->startDocument() ;
}
void do_endDocument(void *p_user_data)
{
// this static method will convert the p_user_data into
// the this pointer...
MySaxBase * saxBase = static_cast<MySaxBase *>(p_user_data) ;
// ...and call the right virtual method
saxBase->endDocument() ;
}
} // extern "C"
MySaxBase::MySaxBase()
{
// the m_sax structure must be set to zero to NULL all its
// pointers to functions
memset(&m_sax, 0, sizeof(xmlSAXHandler)) ;
// Now, we initialize some pointers to the static method we
// want to be called
this->m_sax.startDocument = do_startDocument ;
this->m_sax.endDocument = do_endDocument ;
}
int MySaxBase::parseFile(const std::string & p_filename)
{
// the important thing, here, is the this pointer, passed as
// a user_data parameter
return xmlSAXUserParseFile(&m_sax, this, p_filename.c_str()) ;
}
void MySaxBase::startDocument()
{
// The document started. Override this method to
// actually do something
}
void MySaxBase::endDocument()
{
// The document ended. Override this method to
// actually do something
}
I did not test this, and I never used libxml2, but I guess the code must be Ok, and this should be enough for you to continue on your own: Just add the methods you want to support, initialize the sax handler with the relevant function pointers, and you'll have your class complete.
The MySaxBase::startDocument and MySaxBase::endDocument methods are virtual just for you to derive from MySaxBase and then override those methods.
Edit 2
I'll reproduce here Steve Jessop's excellent comment:
+1. One tiny quibble - I don't think that static member functions are guaranteed by the C++ standard to have C linkage / calling convention, but to use them as a callback from a C API, that's what they need. I don't specifically know what implementations it makes a difference, but for safety do_startDocument should be a free function declared with extern "C". On the same subject: a Java programmer may not realise you have make sure that the function can't throw an exception (because C doesn't have them). So you'd normally want to see a try/catch(...) in the wrapper function. – Steve Jessop
Following this, and after reading Johannes Schaub - litb (who else?) no less excellent answer at static vs extern "C"/"C++" , I modified the code to make do_startDocument and do_endDocument real C functions (i.e. wrapped in an extern "C" block). This usually is not important (I never encountered this kind of problem), but, better safe than sorry.
Your basic problem is that static methods are not per-instance, so there is no this pointer. You somehow need to get a OuterClass* passed to mymethod1 and mymethod2.
If you show us how mymethod1 and mymethod2 are called, we can help you further.
If it's simply called by you someplace where you have a OuterClass object, then your solution is simple:
class OuterClass
{
// ...
static void mymethod1(OuterClass* oc)
{
oc->all_records.push_back( something );
}
};
void some_func()
{
OuterClass oc;
OuterClass::method1(&oc);
}
Since you updated your question here is how you should do this:
class OuterClass {
public:
vector<AttributeSetPtr> allRecords;
void characters(const xmlChar* ch, int len)
{
// do here whatever you want
allRecords.push_back(bla bla);
}
static void static_characters(void* ctx, const xmlChar* ch, int len) {
// retrieve this pointer from ctx
static_cast<OuterClass*>(ctx)->characters(ch, len);
}
};
saxHandler.characters = &OuterClass::static_characters;
...
OuterClass outerClass;
xmlSaxUserParseMemory(&saxHandler, static_cast<void*>(&outerClass), xmlString, xmlString.length());