0

General

I have a library with a class constructor class Math(&foo1,&foo2);, which I would like to put into a library for class Algebra(), where foo1 and foo2 are defined in Algebra.cpp

My current constructor Algebra::Algebra():Math(&Algebra::foo1,&Algebra::foo2) is returning an error in the Arduino IDE to the effect of:

error: no matching function for call to 'Math::Math(void (Algebra::*)(long unsigned int, byte), byte (Algebra::*)(long unsigned int))':Math(&Algebra::foo1, &Algebra::foo2)

Meta Note: I believe this is on topic because I'm dealing specifically with developing code for the Arduino Mega using libraries and hardware components designed for Arduino. If I am in error, and there is a better exchange for this question please let me know


Specifically,

I'm writing a library to combine Adafruit's I2C FRAM with the Extended database library (I have validated that the libraries work when called into a sketch independently, but I'd like to combine them to be more easily inheritable in [Big_Machine_api.h] that I will be making later) I'm testing my library with this sketch:

/*
 EDB_AT24C1024.pde
 Extended Database Library + Adafruit_FRAM_I2C EEPROM Test Sketch 

 The Extended Database library project page is here:
 http://www.arduino.cc/playground/Code/ExtendedDatabaseLibrary

 The Adafruit_FRAM_I2C library project page is here:
 https://github.com/adafruit/Adafruit_FRAM_I2C

 */
#include "Arduino.h"
#include <Wire.h>
#include <Adafruit_FRAM_I2C_EDB.h>
#define TABLE_SIZE 131072

// Arbitrary record definition for this table.  
// This should be modified to reflect your record needs.
struct LogEvent {
  int id;
  unsigned long Rotations;
} 
logEvent;

// Create an EDB object with the appropriate write and read handlers
Adafruit_FRAM_I2C_EDB db;

// Run the demo
void setup() { 
  Serial.begin(115200);
  Serial.println("DONE");
}

void loop() {
}

My ADAFRUIT_FRAM_I2C_EDB.h file:

#ifndef ADAFRUIT_FRAM_I2C_EDB_h
#define ADAFRUIT_FRAM_I2C_EDB_h

#include <Arduino.h>
#include <Adafruit_FRAM_I2C.h>
#include <EDB.h>

#define MB85RC_DEFAULT_ADDRESS        (0x50) /* 1010 + A2 + A1 + A0 = 0x50 default */

class Adafruit_FRAM_I2C_EDB : public EDB {
 public:
  Adafruit_FRAM_I2C_EDB(uint8_t addr = MB85RC_DEFAULT_ADDRESS);
  void getDeviceID(uint16_t *manufacturerID, uint16_t *productID);

 private:
  Adafruit_FRAM_I2C _fram;
  uint8_t _FRAMaddr;
  void writer(unsigned long address, byte data);
  byte reader(unsigned long address);

};
#endif

My ADAFRUIT_FRAM_I2C_EDB.cpp file:

#include "Arduino.h"
#include "Adafruit_FRAM_I2C.h"
#include "EDB.h"
#include "Adafruit_FRAM_I2C_EDB.h"
Adafruit_FRAM_I2C_EDB::Adafruit_FRAM_I2C_EDB(uint8_t addr)
:_FRAMaddr(addr),EDB(&Adafruit_FRAM_I2C_EDB::writer, &Adafruit_FRAM_I2C_EDB::reader) {
  _fram = Adafruit_FRAM_I2C();
  _fram.begin(_FRAMaddr);
}

void Adafruit_FRAM_I2C_EDB::getDeviceID(uint16_t *manufacturerID, uint16_t *productID) {
  _fram.getDeviceID(manufacturerID, productID);
}


void Adafruit_FRAM_I2C_EDB::writer(unsigned long address, byte data) {
  _fram.write8(address, data);
}

byte Adafruit_FRAM_I2C_EDB::reader(unsigned long address) {
  return _fram.read8(address);
}

Full Error List:

C:[...]\Arduino\libraries\Adafruit_FRAM_I2C_EDB\Adafruit_FRAM_I2C_EDB.cpp:16:84: note: candidates are:

In file included from C:[...]\Arduino\libraries\Adafruit_FRAM_I2C_EDB\Adafruit_FRAM_I2C_EDB.cpp:3:0:

C:[...]\Arduino\libraries\EDB-master/EDB.h:54:5: note: EDB::EDB(void (*)(long unsigned int, uint8_t), uint8_t (*)(long unsigned int))

     EDB(EDB_Write_Handler *, EDB_Read_Handler *);

     ^

C:[...]\Arduino\libraries\EDB-master/EDB.h:54:5: note:   no known conversion for argument 1 from 'void (Adafruit_FRAM_I2C_EDB::*)(long unsigned int, byte) {aka void (Adafruit_FRAM_I2C_EDB::*)(long unsigned int, unsigned char)}' to 'void (*)(long unsigned int, uint8_t) {aka void (*)(long unsigned int, unsigned char)}'

C:[...]\Arduino\libraries\EDB-master/EDB.h:50:7: note: constexpr EDB::EDB(const EDB&)

 class EDB {

       ^

C:[...]Arduino\libraries\EDB-master/EDB.h:50:7: note:   candidate expects 1 argument, 2 provided

C:[...]Arduino\libraries\EDB-master/EDB.h:50:7: note: constexpr EDB::EDB(EDB&&)

C:[...]\Arduino\libraries\EDB-master/EDB.h:50:7: note:   candidate expects 1 argument, 2 provided

exit status 1
Error compiling for board Arduino/Genuino Mega or Mega 2560.
  • You only use &foo when constructing if the constructor needs *foo. – Majenko Jul 20 '18 at 16:38
  • Ok, my constructor Algebra::Algebra():Math(Algebra::foo1,Algebra::foo2) results in error: invalid use of non-static member function:Math(Algebra::foo1, Algebra::foo2) Where would I go from here? – ATE-ENGE Jul 20 '18 at 16:42
  • Algebra::Algebra(FooType &foo1, FooType &foo1):Math(foo1, foo2)? – Juraj Jul 20 '18 at 17:08
3

You just pass the variables to the parent constructor in the initialization list of the child. No need for qualifications or anything like that.

Here's an example that compiles:

class Math {
    private:
        int _foo1;
        int _foo2;

    public:    
        Math(int &foo1, int &foo2) : _foo1(foo1), _foo2(foo2) {}
};

class Algebra : public Math {
    private:
        int myFoo1 = 12;
        int myFoo2 = 34;

    public:
        Algebra() : Math(myFoo1, myFoo2) {}
};

Math's constructor takes two integers passed by reference. The Algebra constructor's initialization list calls the parent Math constructor with two of its own member integers that are then automatically passed by reference, since that is what the constructor calls for.

However, that isn't what your actual problem is. You're asking about one thing, then showing an error that is for a completely different problem.

You have a constructor (actually any function will do the same) that expects a pair of pointers to two functions:

  • void (*)(long unsigned int, uint8_t)
  • uint8_t (*)(long unsigned int)

That is, you need two functions, such as:

void reader(unsigned long a, uint8_t b) {
}

and

uint8_t writer(unsigned long a) {
    return 3;
}

But instead you are attempting to pass member functions of a class. The problem here is that although they look the same, because they are class members they aren't the same.

Any class member function has an additional implied parameter, which is a pointer to the containing class instance and is called this. So your functions actually look more like:

void reader(Adafruit_FRAM_I2C_EDB *this, unsigned long a, uint8_t b) {
}

and

uint8_t writer(Adafruit_FRAM_I2C_EDB*this, unsigned long a) {
    return 3;
}

(Note: that's only an approximation - it's actually a lot more involved than that, but it serves to illustrate the problem). As you can see that doesn't match what is expected, and so you can't pass those functions to the parent constructor - they're simply wrong.

This is a commonly occuring problem - often seen when trying to use a class member function with attachInterrupt(). You just can't do it. Or not like that anyway.

The only way of passing a member function directly is for that member function to be static. That then acts like a normal function, and there is no this parameter. However, it can only act on other static variables and functions. So using it takes a little more care - plus of course static functions and variables are shared between all instances of a class.

  • Is there a way I can edit the constructor to accept void writer (Class *this, unsigned long a, uint8_t b) and uint8_t reader (Class *this, unsigned long a) ? I've been trying to make it work, but my FRAM library does not seem to want to work as a static function. – ATE-ENGE Jul 24 '18 at 12:24
  • The parent class would need to know about the child class and explicitly include it in the prototype. Either that or you create a separate interface class that the parent uses in the prototype and the child inherits from. Personally I wouldn't take either route, but would have the parent define some pure virtual read/write function stubs and then create a child class that implements those stubs. – Majenko Jul 24 '18 at 13:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.