gpt4 book ai didi

C++ 等价于 Java 的匿名类

转载 作者:行者123 更新时间:2023-12-04 14:15:38 27 4
gpt4 key购买 nike

我正在将一些 Java 代码翻译成 C++。

在 Java 中,我们可以从匿名类创建对象,使用现有的构造函数,并覆盖一些方法。例如,

class X {
public X(int value) {...}
public void work() {....}
}

void main(String[] args) {
X entity = new X(5) {
public void work() { /* Something else */ }
};
}

在 C++ 中,我知道我可以创建匿名类如下:

class X {
public:
virtual void work() {...}
}

class : public X {
public:
void work() {....}
} obj;

但 C++ 不允许匿名类中的构造函数,并且它不允许从对象扩展(例如, new X(5) { public void work() {} } ,就像 Java 允许的那样.

如何用 C++ 编写类似的代码?

更新 03/07/2020 05:27 CDT

关于我正在处理的问题的更多背景信息。我正在实现内存 SQL 数据库的聚合函数,并使用以下类来表示聚合字段:

class AggField {
public:
AggField(int colIndex);
virtual void reduce(DataRow&) = 0;
virtual double output() = 0;
}

对于每种类型的聚合,例如 avg、min/max 和 sum,我都有一个子类。例如

class Avg : public AggField {
private:
int counter_;
double value_;
public:
Avg(int colIndex) : AggField(colIndex), counter_(0), value_(0) {};
void reduce(DataRow&) override {
value_ += row[colIndex].doubleval();
counter_ += 1;
}
double output() override {
return value_ / counter_;
}
}

class Sum : public AggField {
.....
}

在处理一个表的时候,我会这样写

Table table = ...
auto agg_opr = Agg({
new Sum(0),
new Avg(1)
});
agg_opr.agg(table);

它对第 0 列求和,并对第 1 列求平均值。

有时(罕见)我需要处理多个输入列。例如,对 col1 * (1 + col2) 求和。我不想创建 AggField 的新子类,而是想编写类似于以下内容的内容:

Table table = ...
auto agg_opr = Agg({
new Sum(0) {
void reduce(DataRow& row) {
value_ += row[0].doubleval() * (1 + row[1].doubleval());
}
},
new Avg(1),
new Max(1)
});
agg_opr.agg(table);

最佳答案

我不能说我知道如何编写地道的 Java,但我猜测 Java 中的这种模式可以替代 C++ 中的 lambda。我记得很久以前在使用 Swing 时使用过匿名类。我想我做了这样的事情:

button.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
// ...
}
});

这是用于从类继承并覆盖方法的糖。正是这样做并不是我想要在 C++ 中附加事件监听器的方式。我更愿意这样做:

button.addMouseClickListener([](const MouseEvent &e) {
// ...
});

在事件监听器的情况下,闭包需要存储在 std::function 或类似的东西中。这与虚拟调用的性能大致相同。

我真的不太了解你在哪里使用这个类,但如果你需要把它放在一边(比如事件监听器或其他东西)然后声明这个类很长的路或使用 std::function 可能是最简洁的选项。如果你不需要把它放在一边(比如算法的策略),那么你可以使用仿函数。当然,您可以将仿函数放在一边,但它需要一些模板机制,而且可能不值得(尽管它确实具有更大的灵 active )。

struct MyPolicy {
int doSomething(int i) {
return i * 3;
}

double getSomething() const {
return d;
}

double d;
};

template <typename Policy>
void algorithm(Policy policy) {
// use policy.doSomething and policy.getSomething...
}

在模板中使用仿函数或 lambda 比使用虚函数具有更好的性能。在上面的示例中,编译器可以并且可能会内联对 doSomethinggetSomething 的调用。这对于虚函数是不可能的。

如果我对您要解决的实际问题了解得更多,那么我可能能够写出更具体、更有用的答案。


看到更新后的问题后,我有另一个建议。那就是为自定义聚合函数创建一个子类。当然,这有很多限制。

template <typename Func>
class CustomAgg : public AggField {
public:
CustomAgg(int colIndex, Func func)
: AggField{colIndex}, func{func} {}

void reduce(DataRow &row) override {
func(value, row);
}

double output() override {
return value;
}

private:
Func func;
double value = 0.0;
// could add a `count` member if you want
};

auto agg_opr = Agg({
new CustomAgg{0, [](double &value, DataRow &row) {
value += row[0].doubleval() * (1 + row[1].doubleval());
}},
new Avg(1),
new Max(1)
});

老实说,我认为对您来说最好的解决方案是不要尝试在 C++ 中实现 Java 功能。我的意思是,如果您需要在某些特定操作中处理多个列,那么只需为此创建一个类。不要走任何捷径。给它起一个名字,即使你可能只在一个地方使用它。

关于C++ 等价于 Java 的匿名类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60573648/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com