Как сделать так, чтобы возвращаемый тип функции совпадал с другой функцией? - PullRequest
0 голосов
/ 24 декабря 2018

в нашей учебной книге есть вопрос о функциях объекта.Есть код на с ++, и вопрос хочет, чтобы мы заполнили пробелы.Код выглядит следующим образом:

template <typename Arg, typename Ret> 
class FuncObj {
public:
    typedef Arg argType;
    typedef Ret retType;
    virtual Ret operator()(Arg) = 0;
};

class DivideBy : public FuncObj<int, double> {
protected:
    int divisor;
public:
    DivideBy(int d) {
        this->divisor = d;
    }
    double operator()(int x) {
        return x/((double)divisor);
    }
};

class Truncate : public FuncObj<double, int> {
public:
    int operator()(double x) {
        return (int) x;
    }
};

template < typename Ftype , typename Gtype >
class Compose : public FuncObj <typename Gtype :: argType, typename Ftype :: retType > {
protected:
    Ftype *f; Gtype *g;
public:
    Compose(Ftype f,Gtype g) {
    --------- =f;
    --------- =g; 
    }

    ---------- operator()(____________x) {
        return (_________)((________)(__________)); }
};

Желаемый результат:

void main() {
    DivideBy *d = new DivideBy(2);
    Truncate *t = new Truncate();
    Compose<DivideBy, Truncate> *c1 = new Compose<DivideBy,Truncate>(d,t);
    Compose<Truncate, DivideBy> *c2 = new Compose<Truncate, DivideBy>(t,d);
    cout << (*c1)(100.7) << endl; // Prints 50.0 
    cout << (*c2)(11) << endl; // Prints 5
}

Я действительно не знаю, как завершить этот код, так какую функцию или концепцию c ++ мы должны использовать длясделать эту работу?Если есть ссылка для дальнейшего изучения этой темы, пожалуйста, запишите ее.Благодарю.

Ответы [ 2 ]

0 голосов
/ 24 декабря 2018

Заполнить пробел не очень сложно, но я хочу сказать, что стиль кода действительно ужасен.

template <typename Ftype, typename Gtype>
class Compose : public FuncObj<typename Gtype ::argType, typename Ftype ::retType>
{
  protected:
    Ftype *f;
    Gtype *g;

  public:
    Compose(Ftype *f, Gtype *g) : f(f), g(g){}; // Prefer constructor initialization list.

    typename Ftype ::retType operator()(typename Gtype ::argType arg)
    {
        return (*f)((*g)(arg));
    }
};

int main(int argc, char const *argv[])
{
    auto *d = new DivideBy(2);
    auto *t = new Truncate();
    auto *c1 = new Compose<DivideBy, Truncate>(d, t);
    auto *c2 = new Compose<Truncate, DivideBy>(t, d);
    cout << (*c1)(100.7) << endl;
    cout << (*c2)(11) << endl;
    delete d;
    d = nullptr;
    delete t;
    t = nullptr;
    delete c1;
    c1 = nullptr;
    delete c2;
    c2 = nullptr; // You need to be very careful with bare pointers.Use unique_ptr and shared_ptr in modern C++.
}
0 голосов
/ 24 декабря 2018

Этот код ужасен (как и учебное пособие, если это среднее качество материала).

Во-первых, void main() не является действительной подписью для main.В этом случае должно быть int main().Во-вторых, если Compose предполагается создать с помощью указателей, то его конструктор должен быть объявлен как Compose(Ftype* f, Gtype* g), а не Compose(Ftype f, Gtype g).В-третьих, код должен включать <iostream> и префикс cout и endl с std:: (или использовать using namespace std, но это все равно будет довольно плохо).Наконец, все new должны иметь соответствующий delete, но еще лучше было бы использовать умные указатели или вообще не указывать.

В любом случае, после всего этого заполнение пробелов относительно просто.
Конструктор будет выглядеть так:

Compose(Ftype f,Gtype g) {
    this->f = f;
    this->g = g;
}

... что очень плохо, потому что оно вызывает использование this->, когда в нем нет необходимости (либо называйте параметры по-другому, либо используйте членсписок инициализатора).
И оператор вызова будет записан так:

typename Ftype::retType operator()(typename Gtype::argType x) {
    return (*f)((*g)(x));
}

Тип аргумента и тип возвращаемого значения - это те, которые передаются в базовый класс FuncObj в качестве аргументов шаблона, а затем вызовпросто составляет f и g.

Демо .

Лучший код без использования указателя будет выглядеть так:

template<typename Ftype, typename Gtype>
class Compose : public FuncObj<typename Gtype::argType, typename Ftype::retType> {
protected:
    Ftype f;
    Gtype g;
public:
    Compose(Ftype f, Gtype g)
    : f(f), g(g) {
    }

    typename Ftype::retType operator()(typename Gtype::argType x) {
        return f(g(x));
    }
};

int main() {
    auto d = DivideBy(2);
    auto t = Truncate();
    auto c1 = Compose(d, t);
    auto c2 = Compose(t, d);
    std::cout << c1(100.7) << "\n";
    std::cout << c2(11) << "\n";
}

Демо .

Вместо использования Java-подобных инициализаций Type *var = new Type(args);, просто используйте значение (auto var = Type(args); или Type var(args)).C ++ не является Java.
Обратите внимание, что вам даже не нужно указывать аргументы шаблона для Compose: они выводятся из аргументов конструктора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...