In my computer science class I have an enum value in a header file and I'm having troubles with the get and set functions. I'm quite new to C++. This is part of my header file:
enum class SchoolType {
Elementary = 1,
Secondary = 2
};
class School : public Institution
{
public:
// There are a couple more values here
SchoolType GetSchoolType();
void SetSchoolType(SchoolType typeSchool);
};
And this is part of my .cpp file:
SchoolType GetTypeSchool()
{
return this->_typeSchool;
}
void SetTypeSchool(SchoolType typeSchool)
{
}
But 'this' brings up an error and says that 'this' may only be used inside a nonstatic member function. How can I get that function to work? My computers teacher told me that that is how I should code the get function but I still don't understand, is there something that I'm doing wrong in the header?
For the .cpp file, you should have:
SchoolType School::GetSchoolType() {
return this->_typeSchool;
}
void School::SetSchoolType(SchoolType typeSchool) {
// Insert code here...
}
Basically, in C++ you need to specify what class the function is part of (in this case, School) when defining the member functions, or else the compiler doesn't see it as being part of any class. You also need to keep your method names consistent (GetSchoolType vs GetTypeSchool).
Related
I would like help on how to understand the use of nested use of these C classes containing callbacks
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
}
};
// confusion on the next 3 lines
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string rxValue = pCharacteristic->getValue();
if (rxValue.length() > 0) {
Serial.println("*********");
Serial.print("Received Value: ");
for (int i = 0; i < rxValue.length(); i++)
Serial.print(rxValue[i]);
Serial.println();
Serial.println("*********");
}
}
};
I am from a C background and am confused by the the part of the code highlighted in BOLD. In the second example class MyCallbacks: public BLECharacteristicCallbacks I am confused by the use of the "body of the code" that appears to be inside a function definition. I want to highlight that I am used to writing Code in C and find the way the class is being dereferenced as problematic. I have gone through literature and am unable to find any proper explanation and am blocked. I came across this code while learning about the ESP32 at this location: https://platformio.org/lib/show/1841/ESP32%20BLE%20Arduino/examples?file=BLE_uart.ino
May I kindly request that someone explains the validity of the two class definitions. I do understand that the answer will encompass references to the relevant header files which appears to have the same definitions.
My question is about the syntactic understanding of how these two class definitions need to be interpreted in light of their previous definitions in the header files. Please note that I am from a C background.
There is no nested definition here.
I cleaned up the indentation of your code. From this, we can see that class MyServerCallbacks and class MyCallbacks are defined as separate classes. We can also see that the former defines two member function and that the latter defines one member function.
I have a C++ class using Core Audio structs on OS X.
My initial implementation was like this:
class MyClass
{
private:
AUNode _converterNode;
AURenderCallbackStruct _renderCBStruct;
public:
MyClass();
~MyClass();
inline AUNode* getConverterNode() { return &_converterNode; }
inline AURenderCallbackStruct* AURenderCallbackStruct() { return &_renderCBStruct; }
};
After reading the Poco style guides, I wanted to change the order of the private/public blocks. It then looked like this:
class MyClass
{
public:
MyClass();
~MyClass();
inline AUNode* getConverterNode() { return &_converterNode; }
inline AURenderCallbackStruct* AURenderCallbackStruct() { return &_renderCBStruct; }
private:
AUNode _converterNode;
AURenderCallbackStruct _renderCBStruct;
};
The compiler now tells me that the type AURenderCallbackStruct is unknown and tells me to replace the type name with ::AURenderCallbackStruct. When I do that, there are no compiler errors.
Weirdly, this only appears for the `AURenderCallbackStruct and not the AUNode.
The AURenderCallbackStruct is defined like this:
typedef struct AURenderCallbackStruct {
AURenderCallback inputProc;
void * inputProcRefCon;
} AURenderCallbackStruct;
and AUNode is defined like this:
typedef SInt32 AUNode;
Can anyone explain why the change of order of private/public block produces a compiler error and why the error disappears when adding a ::in front of the type?
First of all it is not clear why you named the member function as AURenderCallbackStruct that coincides with the corresponding structure's name and looks like the structure constructor.
The problem is this stupid name.
in the first case the compiler thinks that you indeed define the member function that hides the corresponding name of the structure.
In the second case the compiler thinks that you trying to call the constructor of the structure.
Simply rename the function that there would not be an ambiguity.
Let us assume the following class:
class FileManipulator
{
static InputTypeOne * const fileone;
InputTypeTwo *filetwo;
public:
FileManipulator( InputTypeTwo *filetwo )
{
this->filetwo = filetwo;
}
int getResult();
};
FileManipulator uses data from both files to obtain output from getResult(). This means multiple iterations over filetwo and multiple constructions of FileManipulators via iterations for different InputTypeTwo objects. Inputs are, let us say, some .csv databases. InputTypeOne remains the same for the whole task.
The program itself is multi-modular and the operation above is only its small unit.
My question is how can I handle that static field in accordance with the object-oriented paradigm and encapsulation. The field must be initialized somehow since it is not a fixed value over different program executions. As far as I understand C++ rules I cannot create a method for setting the field, but making it public and initializing it outside of any class (FileManipulator or a befriended class) seems to me at odds with the encapsulation.
What can I do then? The only thing that comes to my mind is to do it in a C manner, namely initialize it in an isolated enough compilation unit. Is it really all I can do? How would that be solved in a professional manner?
edit
I corrected pointer to constant to constant pointer, which was my initial intention.
You can write a public static method of FileManipulator that would initialize the field for you:
static void init()
{
fileone = something();
}
And then call it from main() or some place where your program is being initialized.
One way of doing this which comes to mind is:
In the .cpp file
FileManipulator::fileone = NULL;
Then modify constructor to do the following:
FileManipulator( InputTypeTwo *filetwo, InputTypeOne *initValue = NULL)
{
if(fileone == NULL)
{
fileone = initValue;
}
this->filetwo = filetwo;
}
Or you could also define an init function and make sure to call it before using the class and after the CTOR. the init function will include the logic of how to init fileone.
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.
Suppose I have a class called Poem.
class Poem{
virtual void recite() = 0;
}
And I have hundreds of .cpp and .hpp files which describe a subclass, like the following
class TheRaven : public Poem{
void recite() { std::cout << "NEVERMORE!" << endl; }
}
And the likes. And in the main function, I'd like to be able to just iterate through every single possible Poem subclasses and call their recite() function. So I made a class:
class PoemRegistry{
std::map<std::string, Poem*> poems;
PoemRegistry& getGlobal(); // returns a static global registry
void register(const std::string& poemname, Poem * thepoem);
};
And then for each poem subclass .cpp file, I put the following.
class TheRavenRegistor{
TheRavenRegistor(){
PoemRegistry::getGlobal().register("theraven", new TheRaven());
}
}
TheRavenRegistor registor();
ninja edit: I put the global class there, forgot about it
Making it easy, I make a shortcut with #define and templates.
Now, the question is, I just heard about the static class initialization fiasco. I suppose this will be immune against it, or is there something I am definitely missing here? Or is there something more elegant that can be used for this purpose?
This is an example for the Singleton design pattern. Don't use a static global, since the initialisation order is undefined across compilation units.
Instead use something like this:
PoemRegistry& PoemRegistry::getGlobal()
{
static PoemRegistry theRegistry; // construction guaranteed when first call
return theRegistry;
}
Make the getGlobal() method static:
class PoemRegistry
{
public:
static PoemRegistry& getGlobal();
...