任务:假设你有以下:
class Thing {
public:
void foo (int, double = 3.14) const {std::cout << "Thing::foo(int, double = 3.14) called.\n";}
void goo (int, double = 1.5) const {std::cout << "Thing::goo(int, double = 1.5) called.\n";}
};
void function1 (const Thing& thing, int a, int b, double c) {
// Code A
thing.foo(a,c);
// Code B
thing.foo(b);
// Code C
}
void function2 (const Thing& thing, int a, int b, double c) {
// Code A
thing.goo(a,c);
// Code B
thing.goo(b);
// Code C
}
我们想写一个辅助函数来捕获function1和function2,这样重复的代码A、B、C就不需要写两次了。
以下将无法编译:
class Thing {
public:
void foo (int, double = 3.14) const {std::cout << "Thing::foo(int, double = 3.14) called.\n";}
void goo (int, double = 1.5) const {std::cout << "Thing::goo(int, double = 1.5) called.\n";}
};
void functionHelper (const Thing& thing, int a, int b, double c, void (Thing::*f)(int, double) const) {
// Code A
(thing.*f)(a,c);
// Code B
// (thing.*f)(b); // Won't compile. Too few arguments passed to (thing.*f), which expects (int, double).
// Code C
}
void function1 (const Thing& thing, int a, int b, double c) {
functionHelper (thing, a, b, c, &Thing::foo);
}
void function2 (const Thing& thing, int a, int b, double c) {
functionHelper (thing, a, b, c, &Thing::goo);
}
第一个解决方案(Thing::foo 和 Thing::goo 的重载):
#include <iostream>
class Thing {
public:
void foo (int, double = 3.14) const {std::cout << "Thing::foo(int, double = 3.14) called.\n";}
void foo_default (int a) const {
std::cout << "Thing::foo_default(int) called.\n";
foo(a);
}
void goo (int, double = 1.5) const {std::cout << "Thing::goo(int, double = 1.5) called.\n";}
void goo_default (int a) const {
std::cout << "Thing::goo_default(int) called.\n";
goo(a);
}
};
void functionHelper (const Thing& thing, int a, int b, double c,
void (Thing::*f)(int, double) const, void (Thing::*g)(int) const) {
// Code A
(thing.*f)(a,c);
// Code B
(thing.*g)(b); // This will compile now, since (thing.*g) expects int only as argument.
// Code C
}
void function1 (const Thing& thing, int a, int b, double c) {
functionHelper (thing, a, b, c, &Thing::foo, &Thing::foo_default);
}
void function2 (const Thing& thing, int a, int b, double c) {
functionHelper (thing, a, b, c, &Thing::goo, &Thing::goo_default);
}
int main() {
Thing thing;
function1 (thing, 2, 5, 1.8);
std::cout << '\n';
function2 (thing, 2, 5, 1.8);
}
输出:
Thing::foo(int, double = 3.14) called.
Thing::foo_default(int) called.
Thing::foo(int, double = 3.14) called.
Thing::goo(int, double = 1.5) called.
Thing::goo_default(int) called.
Thing::goo(int, double = 1.5) called.
第二种解决方案(将Thing::foo 和Thing::goo 包装成函数对象):
#include <iostream>
#include <memory>
class Thing {
public:
void foo (int, double = 3.14) const {std::cout << "Thing::foo(int, double = 3.14) called.\n";}
void goo (int, double = 1.5) const {std::cout << "Thing::goo(int, double = 1.5) called.\n";}
class FooOrGoo {
public:
void operator()(const Thing& thing, int a) const {helper1 (thing, a);}
void operator()(const Thing& thing, int a, double b) {helper2 (thing, a, b);}
virtual ~FooOrGoo() {std::cout << "Thing::FooOrGoo object destroyed.\n";}
private:
virtual void helper1 (const Thing& thing, int a) const = 0;
virtual void helper2 (const Thing& thing, int a, double b) const = 0;
};
class Foo : public FooOrGoo {
virtual void helper1 (const Thing& thing, int a) const override {thing.foo(a);}
virtual void helper2 (const Thing& thing, int a, double b) const override {thing.foo(a, b);}
};
class Goo : public FooOrGoo {
virtual void helper1 (const Thing& thing, int a) const override {thing.goo(a);}
virtual void helper2 (const Thing& thing, int a, double b) const override {thing.goo(a, b);}
};
};
void functionHelper (const Thing& thing, int a, int b, double c, std::unique_ptr<Thing::FooOrGoo> f) {
// Code A
(*f)(thing, a,c);
// Code B
(*f)(thing, b);
// Code C
}
void function1 (const Thing& thing, int a, int b, double c) {
functionHelper (thing, a, b, c, std::unique_ptr<Thing::Foo>(new Thing::Foo)); // 'std::make_unique<Thing::Foo>());' is not supported by GCC 4.8.1.
}
void function2 (const Thing& thing, int a, int b, double c) {
functionHelper (thing, a, b, c, std::unique_ptr<Thing::Goo>(new Thing::Goo)); // 'std::make_unique<Thing::Goo>());' is not supported by GCC 4.8.1.
}
int main() {
Thing thing;
function1 (thing, 2, 5, 1.8);
std::cout << '\n';
function2 (thing, 2, 5, 1.8);
}
输出:
Thing::foo(int, double = 3.14) called.
Thing::foo(int, double = 3.14) called.
Thing::FooOrGoo object destroyed.
Thing::goo(int, double = 1.5) called.
Thing::goo(int, double = 1.5) called.
Thing::FooOrGoo object destroyed.
您认为哪种解决方案更好?我觉得第二个更优雅,但是代码行数更多(没有多态我做不到)。