Переназначение метода в наследуемом классе

clawham
Offline
Зарегистрирован: 26.03.2020

Добрый день. Есть такая замечательная библиотека как LiquidCrystal_I2C

Там все хорошо работает с экраном а все общение с апаратной частью вынесено в метод expanderWrite

Вот мне нужно сделать свой класс который бы аботал один-в-один всеми методами этой библиотеки но метод expanderWrite должен использоваться моим.

Так вот я конечно могу скопировать себе эту библиотеку, подправить ей имена классов и написать свой expanderWrite но это не спортивно чтоли. Теоретически я могу создать свой класс, который будет наследоваться от LiquidCrystal_I2C а уже в нем я теоретически могу заменить этот метод своим но я не совсем понимаю как это сделать? просто написав в своем классе такой же метод с таким же названием но вызывая метод из основного класса - он берет свой же метод а не мой.

class liquid
{
public:
    liquid();
    void go();
private:
    void worker();
};

liquid::liquid()
{
    Serial.println("Liquid created");
}

void liquid::worker()
{
    Serial.println("Liquid worker");
}

void liquid::go()
{
    worker();
}


class liq : public liquid

{
public:
    liq();
private:
    void worker();
};

liq::liq()
{
    Serial.println("Liq created");
}

void liq::worker()
{
    Serial.println("Liq worker");
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println("Started..");
  liquid lc;
  lc.go();

  liq lq;
  lq.go();
}

вот этот код выдает 

Started..
Liquid created
Liquid worker
Liquid created
Liq created
Liquid worker
 
тоесть метод Go из liquid использует метод worker из своего класса а мне надо - чтоб использовал из моего. Это вообще возможно не влезая в родную библиотеку?
rkit
Offline
Зарегистрирован: 23.11.2016

Невозможно.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

У тебя в дочернем классе не переопределен метод go(), а значит вызывается метод родителя liquid::go(), который в свою очередь вызывает свой метод liquid::worker().

1. Переопределить метод go() в дочернем:

class liquid {
  public:
    liquid();
    void go();
  private:
    void worker();
};

liquid::liquid() {
  Serial.println("Liquid created");
}

void liquid::worker() {
  Serial.println("Liquid worker");
}

void liquid::go() {
  worker();
}

class liq : public liquid {
  public:
    liq();
    void go();
  private:
    void worker();
};

liq::liq() {
  Serial.println("Liq created");
}

void liq::go() {
  worker();
}

void liq::worker() {
  Serial.println("Liq worker");
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println("Started..");
  liquid lc;
  lc.go();

  liq lq;
  lq.go();
}

void loop () {

}

2. Переопределить сразу метод worker() и вызывать его напрямую (если это целесообразно):

class liquid {
  public:
    liquid();
    void go();
  private:
    void worker();
};

liquid::liquid() {
  Serial.println("Liquid created");
}

void liquid::worker() {
  Serial.println("Liquid worker");
}

void liquid::go() {
  worker();
}

class liq : public liquid {
  public:
    liq();
    void go();
  private:
    void worker();
};

liq::liq() {
  Serial.println("Liq created");
}

void liq::go() {
  worker();
}

void liq::worker() {
  Serial.println("Liq worker");
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println("Started..");
  liquid lc;
  lc.go();

  liq lq;
  lq.go();
}

void loop () {

}

В обоих случаях у меня вывод такой:

19:39:27.652 -> Started..
19:39:27.652 -> Liquid created
19:39:27.652 -> Liquid worker
19:39:27.699 -> Liquid created
19:39:27.699 -> Liq created
19:39:27.736 -> Liq worker

3. Может быть как-то так попробовать решить задачу?

class liquid {
  public:
    liquid();
    void go();
  private:
    void worker();
};

liquid::liquid() {
  Serial.println("Liquid created");
}

void liquid::worker() {
  Serial.println("Liquid worker");
}

void liquid::go() {
  worker();
}

class liq : public liquid {
  public:
    liq();
    void go();
  private:
    void worker();
};

liq::liq() {
  Serial.println("Liq created");
}

void liq::go() {
  liquid::go();
  worker();
}

void liq::worker() {
  Serial.println("Liq worker");
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println("Started..");
  liquid lc;
  lc.go();

  liq lq;
  lq.go();
}

void loop () {

}
19:47:39.335 -> Started..
19:47:39.335 -> Liquid created
19:47:39.335 -> Liquid worker
19:47:39.382 -> Liquid created
19:47:39.382 -> Liq created
19:47:39.382 -> Liquid worker
19:47:39.382 -> Liq worker

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Если метод не объявлен виртуальным, то все другие методы родительского класса будут вызывать свой метод, а не метод дочернего класса. Потому, либо объявлять виртуальным, либо заменять все методы, которые его вызывают.

b707
Offline
Зарегистрирован: 26.05.2017

clawham пишет:

Это вообще возможно не влезая в родную библиотеку?

совсем не влезая в родную библиотеку - НЕТ