унаследованный шаблонный метод не отображается после добавления метода с тем же именем - PullRequest
0 голосов
/ 23 января 2019

У меня следующая проблема.Класс E переопределяет два метода: один происходит от абстрактного класса D, который наследуется от специализации шаблонного класса C<T>, где T = A.Другой от C<A> напрямую.И оба имеют одно и то же имя.

Теперь D должен иметь доступ к обоим методам: doSomething(const A& a), потому что он наследует его от C, и doSomething(const B& b), потому что D объявляет его.

Однако следующий код не компилируется, поскольку компилятор распознает только метод doSomething(const B&) из указателя на D

#include <iostream>
#include <sstream>
using namespace std;

class A {
private:
    int a = 10;
public:
    inline std::string hello() const{
        std::stringstream ss;
        ss << a;
        return ss.str();
    }
};

class B {
private:
    int b = 20;
public:
    inline std::string hello() const{
        std::stringstream ss;
        ss << b;
        return ss.str();
    }
};

template <class T>
class C {
public:
    inline virtual bool doSomething(const T& t) {
     std::cout << "C is doing something with T" << t.hello() << std::endl;
     return true;
    }
};


class D : public C<A> {
public:
    virtual void doSomething(const B& b) = 0;
};

class E : public D {
public:
    inline bool doSomething(const A& a) override {
        std::cout << "E is doing something with A: " << a.hello() << std::endl;
        return true;
    }

    inline void doSomething(const B& b) override {
        std::cout << "E is doing somethign with B: " << b.hello() << std::endl;
    }
};


int main()
{
  A a;
  B b;
  D* d = new E();

  d->doSomething(b);
  d->doSomething(a); // compile error, does not recognize doSomething(const A&)

  delete d;
}

Компилятор показывает следующую ошибку:

In function ‘int main()’:
main.cpp:62:19: error: no matching function for call to ‘D::doSomething(A&)’
   d->doSomething(a); // compile error, does not recognize doSomething(const A&)
                   ^
main.cpp:39:18: note: candidate: virtual void D::doSomething(const B&)
     virtual void doSomething(const B& b) = 0;
                  ^
main.cpp:39:18: note:   no known conversion for argument 1 from ‘A’ to ‘const B&’

Почему это?

Ответы [ 2 ]

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

Чтобы сделать функцию базового класса видимой в производном классе, который скрыт функцией с тем же именем, вы должны использовать директиву using (using C<A>::doSomething;).

Однако я также хочудобавить, что GCC 8.2 сообщает, что в коде есть неопределенное поведение при delete d.Это потому, что класс D имеет не виртуальный деструктор.

warning: deleting object of abstract class type 'D' which has non-virtual destructor will cause undefined behavior [-Wdelete-non-virtual-dtor]
       delete d;

См. Демоверсию здесь .

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

Это происходит потому, что компилятор не автоматически объединяет все функции из базовых классов с набором перегруженных функций для выбора. Это набор перегруженных функций, учитываемых при вызове d->doSomething(a);, состоит только из D::doSomething(const B& b). Чтобы это исправить, вам нужно привести C<A>::doSomething; в D класс

 class D : public C<A> {
 public:
     using C<A>::doSomething;
     virtual void doSomething(const B& b) = 0;
 };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...