Как я могу имитировать переопределение родительской функции (не скрывая) в C ++? - PullRequest
0 голосов
/ 23 января 2019

Из прочтения этого ответа ( Возможно ли переопределить функцию в дочернем классе C ++ без использования виртуального ключевого слова для функции в родительском классе, который является абстрактным? ), очевидно, что нельзя переопределить родительский классфункция из дочернего класса.

Тем не менее, мне нужно что-то, что работает, как это.Вот нефункциональная установка, которая описывает то, что я пытаюсь сделать.

class Parent {
public:
  Graph createGraph() {
    return new Graph([this](float x){ 
        return this->getY(x); 
    });
  }

  float getY(float x) {
    return sin(x);
  }
}

.

class Child: public Parent {
public:
  float getY(float x) {
    return x * x;
  }
}

Важными моментами моей настройки является то, что у меня есть родительский класс, который имеетфункция, которая последовательно ссылается на функцию, которая часто перегружается дочерними классами.Исходя из земли Java / Javascript, мой подход заключается в том, чтобы сделать то, что вы видите выше, но, похоже, я неправильно думаю об этом для c ++.

Как я могу симулировать (то есть получить относительно схожую функциональность) с этимформа переопределения?

Я знаю, что, не будучи СУХИМ, я мог бы скопировать / paset createGraph в оба, и это сработало бы.И если так поступил бы опытный разработчик c ++, то для меня этого достаточно.Но сейчас я ищу способ подойти к этой проблеме, такой же СУХОЙ, как мой более похожий на java способ.

РЕДАКТИРОВАТЬ: казалось бы, основная проблема здесь заключается в том, что я неправильно понял, что virtualделает, предполагая, что это означает, что не может быть определения функции в родительском классе (аналогично абстрактным функциям в других языках).Дело обстоит не так, кажется, что virtual делает что-то еще, что допускает абстрактные классы, но не требует их.

Ответы [ 4 ]

0 голосов
/ 23 января 2019

Как работают функции вызова:

struct Parent{
  virtual void foo(){} // Func(1)
  void call(){
    this->foo();         // (A) call final overrider
    this->Parent::foo(); // (B) call Parent::foo
    }
  };

struct Derived:Parent{
  void foo() override {} // Func(2)
  };

void test(){
  Parent parent; //final overrider of foo is Func(1)
  Derived derived1; //final overrider of foo is Func(2)
  Parent& derived2 = derived; //final overrider of foo is Func(2).

  parent.call()//  At (A) call => Func(1)
               //  At (B) call => Func(1)

  derived1.call()  // At (A) call => Func(2)
                   // At (B) call => Func(1)

  derived2.call()  // At (A) call => Func(2)
                   // At (B) call => Func(1)
0 голосов
/ 23 января 2019

использовать шаблон CRTP. https://gcc.godbolt.org/z/J_N5Y_

void sink(int);
template<class ChildT>
struct Parent {
    void doStuff(){
        sink(
            static_cast<ChildT*>(this)->getY()
            );
    }
    int getY() {
        return 42;
    }
};
struct Child : Parent<Child> {
    int getY() {
        return 43;
    }
};
struct Child2 : Parent<Child2> {
//Does not want to customize, default is fine.
};
void foo() {
    Child c;
    c.doStuff(); # passes 43
    Child2 c2;
    c2.doStuff(); # passes 42
}
0 голосов
/ 23 января 2019

Не уверен, что то, что вы ищете, еще не было предоставлено в указанной вами ссылке, но именно так вы бы реализовали переопределение в C ++.

class Parent
{
public:
    virtual ~Parent() = default;

    Graph createGraph(float x)
    {
        return Graph(getY(x));
    }

    virtual float getY(float x) const
    {
        return sin(x);
    }
};

class Child: public Parent
{
public:
    float getY(float x) const override
    {
        return x * x;
    }
};

int main()
{
    // Play around here with creating a Parent instead of a Child
    //    and/or taking away the virtual keyword to learn how this works
    std::unique_ptr<Parent> thingy = std::make_unique<Child>();
    thingy->createGraph(1.0f);
}
0 голосов
/ 23 января 2019

в родительском классе вы должны сделать функции, которые вы хотите переопределить, как виртуальные, например:

 class Parent{
 virtual float getY(float x) {
    return sin(x);
  }}
...