6

and I am facing a trouble with polymorphic classes and inheritance.

I have a parent class

//calibration.h 
class Calibration {
private:
public:
void init();
void calc():
void close();
void saveFile();
}

//calibration.cpp
Calibration::Calibration(){}
void Calibration::saveFile(){
std::ofstream out;
    out.open("cores.arff");
out << " " << std::endl;
out.close();
}

and I have two children

//automatic.cpp 
Automatic::Automatic(){}
void Automatic::config(){
....
}
void Automatic::calibrate(){
....
}

void Calibrate::init(){
 Automatic::config();
}


//manual.h
#include "calibration.h"
class Manual : public Calibration {
public:
void calibrate();
}


//manual.cpp 
Manual::Manual(){}

void Manual::calibrate(){
....
}

void Calibrate::init(){
 Manual::calibrate();
}

How I correct call Manual::calibrate and Automatic::config from Calibrate::init() ?

I have tried:

void Calibrate::init(){
 Automatic::config();
}

but the error I got was:

error: no member function declared in class 'automatic'

LRDPRDX
  • 631
  • 1
  • 11
  • 23
schirrel
  • 303
  • 2
  • 4
  • 7
  • 1
    The header file for automatic would be handy – Ed Heal Jun 16 '16 at 19:55
  • someone have answered your question, question [link](http://stackoverflow.com/questions/357307/how-to-call-a-parent-class-function-from-derived-class-function) – aex Jun 16 '16 at 19:58

2 Answers2

12

In object oriented programming this issue is addressed best with member function overloading.

Make the Calibrate::init() virtual

virtual void init();

overload the init method in each subclass, and call the child specific methods in each.

class Manual : public Calibration {
public:
void init();
void calibrate();
}

Manual::init()
{
   this->calibrate();
}
UmNyobe
  • 22,539
  • 9
  • 61
  • 90
  • Proper solution. Just that, `init()` does not need to be virtual. – smokku Jun 16 '16 at 20:16
  • Using this way i can`t access init from outside. I have a class that contains manual, and it must do the init, like m.init(). But it says that it is an undefiened referenec – schirrel Jun 16 '16 at 20:53
2

The simplest route is to have only one function, calibrate that is virtual and overridden by subclasses of Calibration.

For this I prefer and demonstrate a pure virtual function. The compiler will catch the mistake if a subclass does not implement pure virtual calibration. If pure virtual is not the right choice for your class hierarchy, define the children's calibrate methods as void calibrate() override; to catch future mistakes should the calibrate method be changed and no longer match.

There is a strong case to be made for making calibrate a protected function so that it cannot be called directly, forcing Calibration's users to use the init function and ensuring the device is fully initialized.

To keep the following code clean, I have removed the unused functions.

#include <iostream>

class Calibration {
public:
    virtual ~Calibration() {}; // must specify virtual destructor to ensure 
                               // proper destruction of all classes involved
    void init();
    virtual void calibrate() = 0; // pure virtual function must be implemented 
                                  // by children or compile will fail
};

// two subclasses to demonstrate
class Automatic : public Calibration {
private:
    void config(); // called through calibrate so should not be directly exposed
public:
    void calibrate(); // implements Calibration::calibrate
};

class Manual : public Calibration {
public:
    void calibrate(); // implements Calibration::calibrate
};

//Implement functions
void Calibration::init()
{
    calibrate(); //calls calibrate function implemented by subclasses
}

//Automatic uses calibrate to call config to keep Calibration's interface simple
void Automatic::calibrate()
{
    std::cout << "called Automatic::calibrate" << std::endl;
    config();
}

void Automatic::config()
{
    std::cout << "called Automatic::config" << std::endl;
}

//Manual uses calibrate to do whatever manual needs to do to calibrate
void Manual::calibrate()
{
    std::cout << "called Manual::calibrate" << std::endl;
}


//demonstration 
int main()
{
    Automatic a;
    a.init(); // can directly init an Automatic. 
    // This will call Calibrate::init, which will then call the correct calibrate

    Manual m;
    m.init(); // or a manual

    Calibration * c = new Automatic();
    c->init(); // magic of polymorphism calls correct calibrate
    delete c;

    c = new Manual();
    c->init();
    delete c;
}
user4581301
  • 33,082
  • 7
  • 33
  • 54