【问题标题】:How to make return type of a function to be same as another function?如何使函数的返回类型与另一个函数相同?
【发布时间】:2018-12-24 06:18:45
【问题描述】:

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

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++ 的什么特性或概念来完成这个工作呢?如果有关于这个主题的进一步研究的链接,请写下来。 谢谢。

【问题讨论】:

  • 这个->f = &f;这->g = &g; ?
  • 老实说,你的学习书不值得印在纸上。作者甚至没有费心去验证这个重要的代码是否没有错误。
  • 附带说明:删除所有new*,它们是不需要的,并且由于您不删除它们而导致内存泄漏。更多详情请见stackoverflow.com/q/184537/2466431
  • 代码非常不好!这本书的作者不知道构造函数是如何工作的!在构造函数的主体中覆盖而不是在初始化列表中使用初始化或多或少是失败的。也许这些类型不是默认可构造的,并且所有代码都停止了。我们在哪里可以找到所有不需要的“新”的“删除”?请拿一本更好的书告诉你的老师,这种代码质量永远不能用于生产!

标签: c++ c++11 inheritance


【解决方案1】:

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

首先,void main() 不是main 的有效签名。在这种情况下,它应该是int main()。其次,如果Compose应该用指针构造,那么它的构造函数应该声明为Compose(Ftype* f, Gtype* g),而不是Compose(Ftype f, Gtype g)。第三,代码应包含&lt;iostream&gt; 和前缀coutendlstd::(或使用using namespace std,但这仍然很糟糕)。最后,所有new 都应该有一个对应的delete,但更好的是使用智能指针,或者根本不使用指针。

不管怎么说,填空还是比较简单的。
构造函数会这样写:

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

...这很糟糕,因为它在不必要时强制使用this-&gt;(或者以不同的方式命名参数,或者使用成员初始化列表)。
呼叫操作员会这样写:

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 指定模板参数:它们是从构造函数参数推导出来的。

【讨论】:

  • @paulsm4 大多数时候自动是可选的。但有时你真的不知道类型和auto是必要的,auto f = []() { ... };
  • @paulsm4 这是另一场辩论。 auto 是我真正喜欢 现代 C++ 的原因之一。我对此有论据。如果您不喜欢在其他语言中使用 auto 和类似内容,我不介意,但这并不是重点。
【解决方案2】:

填空并不难,但我想说代码风格真的很糟糕。

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

【讨论】:

    猜你喜欢
    • 2018-12-24
    • 2011-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-14
    • 2021-07-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多