如何使一个函数的返回类型与另一个函数相同?

时间:2018-12-24 06:18:46

标签: c++ c++11 inheritance

我们的学习书中有一个关于对象函数的问题。 c ++中有一个代码,这个问题想让我们填补空白。代码如下

videoPreviewLayer

理想的结果是

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

我真的不知道如何完成这段代码,那么我们应该使用c ++的哪些功能或概念来完成这项工作?如果有关于此主题的进一步研究链接,请写下来。 谢谢。

2 个答案:

答案 0 :(得分:5)

这段代码很糟糕(如果那是材料的平均质量,那么学习书也是如此)。

首先,void main()不是main的有效签名。在这种情况下,它应该为int main()。其次,如果假设Compose是使用指针构造的,则其构造函数应声明为Compose(Ftype* f, Gtype* g),而不是Compose(Ftype f, Gtype g)。第三,代码应包括<iostream>并在前缀coutendl的前面加上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的那些类型,然后调用仅组成fg

Demo

不使用任何指针的更好的代码如下所示:

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";
}

Demo

不要使用类似Java的初始化方法Type *var = new Type(args);,而要使用值(auto var = Type(args);Type var(args))。 C ++不是Java。
请注意,您甚至不需要为Compose指定模板参数:它们是从构造函数参数中推导出来的。

答案 1 :(得分:0)

填充空白不是很困难,但是我想说代码风格确实很糟糕。

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++.
}