c++ - 如何简化适配器方案?
问题描述
为了说明清楚,我先贴出“如何使用”的代码:
AB.h:
#include <vector>
#include <list>
// execpt they both have children, A & B share nothing in common,
// even children use different containers
struct A {
int num;
std::vector<A> children;
};
struct B {
std::string s;
float n;
std::list<B> children;
};
主.cpp:
#include "Node.h"
// handle A & B with the common interface Node
// do not use template, since in practice, print() may be a large library
void print(Node& n) {
printf("%s\n", n.tell().c_str());
for (auto& c : n.children()) {
print(c);
}
}
////////////////////////////////////////////////////////////////////////////////
int main() {
A a { .num = 3, .children = { { .num = 7 }, { .num = 8 } } };
NodeA na(&a); // wrap A with NodeA adapter
print(na);
B b {
.s = "Will", .n = 1,
.children = { { .s = "Ryu", .n = 5 }, { .s = "Ken", .n = 8 } }
};
NodeB nb(&b); // wrap B with NodeB adapter
print(nb);
}
编译运行:
WilldeMacBook-Pro:testNodes Will$ cc -std=c++11 -lc++ main.cpp Node.cpp
WilldeMacBook-Pro:testNodes Will$ ./a.out
3
7
8
Will1.000000
Ryu5.000000
Ken8.000000
它确实有效,以通用的方式处理不同的 A 和 B,运行时开销很小,并且......简单明了......直到你看到 Node.h:
#include <memory>
#include <sstream>
#include "AB.h"
////////////////////////////////////////////////////////////////////////////////
struct Node;
struct Nodes;
struct NodeIter;
struct NodeIterPtr;
struct Node { // the only interface i care about, other three are "have-to" ones
virtual std::string tell() = 0;
virtual Nodes& children() = 0;
};
struct Nodes {
virtual NodeIterPtr begin() = 0;
virtual NodeIterPtr end() = 0;
};
struct NodeIter {
virtual ~NodeIter() {}
virtual Node& operator*() = 0;
virtual NodeIter& operator++() = 0;
virtual bool operator!=(const NodeIter& other) = 0;
};
struct NodeIterPtr {
NodeIterPtr(NodeIter* p) : ptr(p) {}
Node& operator*() { return (*ptr).operator*(); }
NodeIter& operator++() { return (*ptr).operator++(); }
bool operator!=(const NodeIterPtr& other) {
return (*ptr).operator!=(*other.ptr);
}
private:
std::shared_ptr<NodeIter> ptr;
};
////////////////////////////////////////////////////////////////////////////////
// adapter for A
struct NodeA : public Node {
NodeA(A* p) : ptr(p) {}
std::string tell() { return std::to_string(ptr->num); }
Nodes& children();
private:
A* ptr;
};
struct NodesA : public Nodes {
NodesA(std::vector<A>* ns) : nodes(ns) {}
NodeIterPtr begin();
NodeIterPtr end();
private:
std::vector<A>* nodes;
};
struct NodeIterA : public NodeIter {
NodeIterA(A* p) : ptr(p) {}
Node& operator*() { static NodeA a(nullptr); a = NodeA(ptr); return a; }
NodeIter& operator++() { ptr++; return *this; }
bool operator!=(const NodeIter& other) {
auto realOther = (const NodeIterA&)(other);
return ptr != realOther.ptr;
}
private:
A* ptr;
};
////////////////////////////////////////////////////////////////////////////////
// adapter for B
struct NodeB : public Node {
NodeB(B* p) : ptr(p) {}
std::string tell() { return ptr->s + std::to_string(ptr->n); }
Nodes& children();
private:
B* ptr;
};
struct NodesB : public Nodes {
NodesB(std::list<B>* ns) : nodes(ns) {}
NodeIterPtr begin();
NodeIterPtr end();
private:
std::list<B>* nodes;
};
struct NodeIterB : public NodeIter {
NodeIterB(std::list<B>::iterator i) : iter(i) {}
Node& operator*() { static NodeB b(nullptr); b = NodeB(&(*iter)); return b; }
NodeIter& operator++() { iter++; return *this; }
bool operator!=(const NodeIter& other) {
auto realOther = (const NodeIterB&)(other);
return iter != realOther.iter;
}
private:
std::list<B>::iterator iter;
};
和 Node.cpp:
#include "Node.h"
Nodes& NodeA::children() {
static NodesA c(nullptr);
c = NodesA(&ptr->children);
return c;
}
NodeIterPtr NodesA::begin() {
auto iter = new NodeIterA(&(*nodes->begin()));
return NodeIterPtr(iter);
}
NodeIterPtr NodesA::end() {
auto iter = new NodeIterA(&(*nodes->end()));
return NodeIterPtr(iter);
}
////////////////////////////////////////////////////////////////////////////////
Nodes& NodeB::children() {
static NodesB c(nullptr);
c = NodesB(&ptr->children);
return c;
}
NodeIterPtr NodesB::begin() {
auto iter = new NodeIterB(nodes->begin());
return NodeIterPtr(iter);
}
NodeIterPtr NodesB::end() {
auto iter = new NodeIterB(nodes->end());
return NodeIterPtr(iter);
}
我真的觉得太复杂了,要实现这么简单的目标。(如果 A 和 B 有多个容器成员,例如学生/员工/门票,那简直就是地狱。) C++ 是为此设计的吗?我什至想到了一些返回基类引用而不是基类指针的奇怪想法。无论如何,我想问的是,有没有办法简化上面的代码?俗话说,“说话便宜,给我看代码”,在谈论任何哲学之前,我更喜欢看到可以直接编译和运行的代码,相同的输出,相同的简单使用方式,但降低了 Node.js 的复杂性。 h/cpp. 谢谢。
解决方案
推荐阅读
- aws-codepipeline - 如何在 AWS CodeBuild Standard Linux 2.0 (Ubuntu 18.0) 中安装 Maven
- r - R中的趋势()函数是什么
- node.js - Typescript中工作线程上的编译错误
- javascript - TypeError: moment__WEBPACK_IMPORTED_MODULE_3___default(...)(...).calendar(...).sort 不是函数
- hp-uft - UFT 报告已损坏
- hibernate - 带有自定义子查询的集合字段
- python - count() 的奇怪执行次数
- ruby-on-rails - 如何覆盖 ActiveModel::SecurePassword.authenticate 方法?
- python - Pandas 使用另一个系列作为查找值在一行中查找关键字的位置
- linux - 无法重新加载 Nginx