2016-06-16 4 views
0

и я столкнулся с проблемой полиморфных классов и наследования.Лучший способ вызова метода Child из родителя в наследование C++

У меня есть родительский класс

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(); 
} 

и у меня есть двое детей

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(); 
} 

Как я исправлю позвонить Manual::calibrate и Automatic::config от Calibrate::init()?

Я попытался:

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

но ошибка я получил, был:

error: no member function declared in class 'automatic'

+1

Заголовочный файл для автоматического будет удобно –

+0

кто-то ответил на ваш вопрос, вопрос [ссылка] (http://stackoverflow.com/questions/357307/how-to-call-a-parent-class- function-from-производный-класс-функция) – aex

ответ

2

В объектно-ориентированном программировании эта проблема решается лучше всего с функцией членом перегрузкой.

Сделать Calibrate::init() виртуальный

virtual void init(); 

перегрузить метод инициализации в каждом подклассе, и вызвать ребенку конкретные методы в каждом.

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

Manual::init() 
{ 
    this->calibrate(); 
} 
+0

Правильное решение. Просто, 'init()' не обязательно должен быть виртуальным. – smoku

+0

Используя этот способ, я не могу получить доступ к init извне. У меня есть класс, который содержит руководство, и он должен выполнить init, как m.init(). Но это говорит о том, что это неоспоримый референц – schirrel

0

Самый простой маршрут должен иметь только одну функцию, которая calibrate виртуальный и переопределены подклассами Calibration.

Для этого я предпочитаю и демонстрирую чистую виртуальную функцию. Компилятор поймает ошибку, если подкласс не реализует чистый виртуальный calibration. Если чистый виртуальный не является правильным выбором для вашей иерархии классов, определите методы calibrate для детей как void calibrate() override;, чтобы поймать будущие ошибки, если метод calibrate будет изменен и больше не будет соответствовать.

Для защиты функции существует специальная функция, так что она не может быть вызвана напрямую, заставляя пользователей Calibration использовать функцию init и гарантируя, что устройство полностью инициализировано.

Чтобы сохранить следующий код в чистоте, я удалил неиспользуемые функции.

#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; 
} 
Смежные вопросы