c ++:双重层次结构中的交叉交互
c++: cross interactions within dual hierarchy
在 C++ 应用程序中,我有两个 class 层次结构,一个用于 Worker
,一个用于 Stuff
。我希望 Worker
的每个子 class 通过 do_stuff
函数与 Stuff
的每个子 class 进行不同的交互。我不确定如何在不系统地向下转换 do_stuff
内的 worker
和 stuff
并对每种可能性进行特定处理的情况下做到这一点。
将 do_stuff
移动为 Worker
或 Stuff
的一种方法并在子 classes 中覆盖消除了对一个向下转换的需要,但是不是另一个。
是否有处理类似案例的特定良好做法?
代码结构如下:
class Worker;
class Worker1 : public Worker;
class Worker2 : public Worker;
class Stuff;
class StuffA : public Stuff;
class StuffB : public Stuff;
void do_stuff(Worker worker, Stuff stuff);
int main() {
vector<Worker*> worker_vec = whatever;
vector<Stuff*> stuff_vec = whatever;
for(Worker* worker : worker_vec) {
for(Stuff* stuff: stuff_vec) {
do_stuff(*worker, *stuff);
}
}
return 0;
}
实现起来有点费力,但至少是可能的:
class Worker1;
class Worker2;
class Stuff
{
public:
virtual ~Stuff() { }
virtual void doStuff(Worker1*) = 0;
virtual void doStuff(Worker2*) = 0;
};
class Worker
{
public:
virtual ~Worker() { }
virtual void doStuff(Stuff* stuff) = 0;
};
class Worker1 : public Worker
{
void doStuff(Stuff* stuff) override
{
stuff->doStuff(this);
}
};
// another approach: CRTP; spares the work of having to rewrite
// the overridden function again and again...
template <typename T>
class Stuffer : public Worker
{
public:
void doStuff(Stuff* stuff) override
{
stuff->doStuff(static_cast<T*>(this));
}
};
class Worker2 : public Stuffer<Worker2>
{
};
class Worker2 : public Worker
{
void doStuff(Stuff* stuff) override
{
stuff->doStuff(this);
}
};
class StuffA : public Stuff
{
public:
void doStuff(Worker1*) override
{
std::cout << "StuffA + Worker1\n";
}
void doStuff(Worker2*) override
{
std::cout << "StuffA + Worker2\n";
}
};
class StuffB : public Stuff
{
public:
void doStuff(Worker1*) override
{
std::cout << "StuffB + Worker1\n";
}
void doStuff(Worker2*) override
{
std::cout << "StuffB + Worker2\n";
}
};
int main()
{
std::vector<Worker*> worker_vec = { new Worker1, new Worker2 };
std::vector<Stuff*> stuff_vec = { new StuffA, new StuffB };
for(Worker* worker : worker_vec)
{
for(Stuff* stuff: stuff_vec)
{
worker->doStuff(stuff);
}
}
return 0;
}
全部没有明确的 (dynamic_
)casts...
对于 Worker2
我通过奇怪的重复模板模式进行了实现 – re-introducing 是的,但是 static_cast
在运行时是免费的,所以可能不会头脑。这将使您不必一次又一次地编写重写函数...
演示 godbolt。
在 C++ 应用程序中,我有两个 class 层次结构,一个用于 Worker
,一个用于 Stuff
。我希望 Worker
的每个子 class 通过 do_stuff
函数与 Stuff
的每个子 class 进行不同的交互。我不确定如何在不系统地向下转换 do_stuff
内的 worker
和 stuff
并对每种可能性进行特定处理的情况下做到这一点。
将 do_stuff
移动为 Worker
或 Stuff
的一种方法并在子 classes 中覆盖消除了对一个向下转换的需要,但是不是另一个。
是否有处理类似案例的特定良好做法?
代码结构如下:
class Worker;
class Worker1 : public Worker;
class Worker2 : public Worker;
class Stuff;
class StuffA : public Stuff;
class StuffB : public Stuff;
void do_stuff(Worker worker, Stuff stuff);
int main() {
vector<Worker*> worker_vec = whatever;
vector<Stuff*> stuff_vec = whatever;
for(Worker* worker : worker_vec) {
for(Stuff* stuff: stuff_vec) {
do_stuff(*worker, *stuff);
}
}
return 0;
}
实现起来有点费力,但至少是可能的:
class Worker1;
class Worker2;
class Stuff
{
public:
virtual ~Stuff() { }
virtual void doStuff(Worker1*) = 0;
virtual void doStuff(Worker2*) = 0;
};
class Worker
{
public:
virtual ~Worker() { }
virtual void doStuff(Stuff* stuff) = 0;
};
class Worker1 : public Worker
{
void doStuff(Stuff* stuff) override
{
stuff->doStuff(this);
}
};
// another approach: CRTP; spares the work of having to rewrite
// the overridden function again and again...
template <typename T>
class Stuffer : public Worker
{
public:
void doStuff(Stuff* stuff) override
{
stuff->doStuff(static_cast<T*>(this));
}
};
class Worker2 : public Stuffer<Worker2>
{
};
class Worker2 : public Worker
{
void doStuff(Stuff* stuff) override
{
stuff->doStuff(this);
}
};
class StuffA : public Stuff
{
public:
void doStuff(Worker1*) override
{
std::cout << "StuffA + Worker1\n";
}
void doStuff(Worker2*) override
{
std::cout << "StuffA + Worker2\n";
}
};
class StuffB : public Stuff
{
public:
void doStuff(Worker1*) override
{
std::cout << "StuffB + Worker1\n";
}
void doStuff(Worker2*) override
{
std::cout << "StuffB + Worker2\n";
}
};
int main()
{
std::vector<Worker*> worker_vec = { new Worker1, new Worker2 };
std::vector<Stuff*> stuff_vec = { new StuffA, new StuffB };
for(Worker* worker : worker_vec)
{
for(Stuff* stuff: stuff_vec)
{
worker->doStuff(stuff);
}
}
return 0;
}
全部没有明确的 (dynamic_
)casts...
对于 Worker2
我通过奇怪的重复模板模式进行了实现 – re-introducing 是的,但是 static_cast
在运行时是免费的,所以可能不会头脑。这将使您不必一次又一次地编写重写函数...
演示 godbolt。