我在类中封装了一个状态机之类的东西。这可以通过依次调用一系列成员函数来完成操作。我还有几个派生类,我想对它们执行相同的序列。有一种方法,我可以模板这个代码?
#include <iostream>
class MyClass {
std::string name;
public:
typedef void (MyClass::*Function)(std::ostream &ostr);
void Func1(std::ostream &ostr) { ostr << "F1" << name << std::endl; };
void Func2(std::ostream &ostr) { ostr << "F2" << std::endl; };
static Function printers[];
void Print(std::ostream &ostr);
};
MyClass::Function MyClass::printers[] = {
&MyClass::Func1,
&MyClass::Func2,
NULL
};
void MyClass::Print(std::ostream &ostr)
{
// various stuff to do before
// ...
int i = 0;
for (Function *fp = printers; *fp; fp++, i++) {
std::cerr << "Calling function " << i << std::endl;
((this)->*(*fp))(ostr);
std::cerr << "Called function " << i << std::endl;
}
// other stuff here...
}
class DerClass: public MyClass {
int index;
public:
typedef void (DerClass::*Function)(std::ostream &ostr);
void Func3(std::ostream &ostr) { ostr << "F3" << index << std::endl; };
static Function printers[];
void Print(std::ostream &ostr);
};
DerClass::Function DerClass::printers[] = {
&DerClass::Func1,
&DerClass::Func3,
NULL
};
// I'd rather not repeat all this stuff, can I template it??
void DerClass::Print(std::ostream &ostr)
{
// various stuff to do before
// ...
int i = 0;
for (Function *fp = printers; *fp; fp++, i++) {
std::cerr << "Calling function " << i << std::endl;
((this)->*(*fp))(ostr);
std::cerr << "Called function " << i << std::endl;
}
// other stuff here...
}
int main()
{
MyClass cl1;
cl1.Print(std::cout);
DerClass cl2;
cl2.Print(std::cout);
}
代码运行,工作,但我想只写一次打印例程,而不是为每个新类,有办法做到这一点,模板?其他类?
我希望是这样的
template <class T>
void T::Print(std::ostream &str) {
int i = 0;
for (Function *fp = printers; *fp; fp++, i++) {
std::cerr << "Calling function " << i << std::endl;
((this)->*(*fp))(ostr);
std::cerr << "Called function " << i << std::endl;
}
}
这不能编译。
错误:无效使用模板类型参数' T ' voidT::Print(std::ostream &str) {
我宁愿把它写成注释,但是代码量根本就不容易读。
下面你可以找到一个关于如何"继承"你的Print
的可能的解决方案。
这只能作为建议或提示。特别是printers
的初始化并没有以一种"好的方式"完成。
希望对你有所帮助
#include <iostream>
#include <string>
template <class Derived>
class MyClass {
std::string name;
protected:
typedef void (Derived::*Function)(std::ostream &ostr);
Function* printers;
public:
MyClass()
:printers(nullptr)
{
}
~MyClass()
{
delete[] printers;
}
virtual void initPrinters()
{
if (printers == nullptr)
{
printers = new Function[3];
printers[0] = &MyClass<Derived>::Func1;
printers[1] = &MyClass<Derived>::Func2;
printers[2] = NULL;
}
}
void destroyPrinters()
{
if (printers != nullptr)
{
delete[] printers;
}
}
void Print(std::ostream &ostr)
{
initPrinters();
// various stuff to do before
// ...
int i = 0;
for (Function *fp = printers; *fp; fp++, i++) {
std::cerr << "Calling function " << i << std::endl;
(((Derived*)this)->*(*fp))(ostr);
std::cerr << "Called function " << i << std::endl;
}
// other stuff here...
}
void Func1(std::ostream &ostr) { ostr << "F1" << name << std::endl; };
void Func2(std::ostream &ostr) { ostr << "F2" << std::endl; };
};
template <>
class MyClass<void> : public MyClass<MyClass<void>>
{
};
class DerClass : public MyClass<DerClass> {
int index;
public:
virtual void initPrinters() override
{
if (printers == nullptr)
{
printers = new Function[3];
printers[0] = &DerClass::Func1;
printers[1] = &DerClass::Func3;
printers[2] = NULL;
}
}
void Func3(std::ostream &ostr) { ostr << "F3" << index << std::endl; };
};
int main()
{
MyClass<void> cl1;
cl1.Print(std::cout);
DerClass cl2;
cl2.Print(std::cout);
}
EDIT: Second Approach
在我看来这个更漂亮。此外,它是更少的代码,它可以由编译器优化:
#include <iostream>
#include <string>
class MyClass {
std::string name;
protected:
template <class T>
void print(std::ostream &ostr, void(T::*printFunc)(std::ostream&))
{
(((T*)this)->*printFunc)(ostr);
}
template <class T, typename... PrintFunctions>
void print(std::ostream &ostr, void(T::*printFunc)(std::ostream&), PrintFunctions... printFuncs)
{
(((T*)this)->*printFunc)(ostr);
print(ostr, printFuncs...);
}
public:
virtual void Print(std::ostream &ostr)
{
print(ostr, &MyClass::Func1, &MyClass::Func2);
}
void Func1(std::ostream &ostr) { ostr << "F1" << name << std::endl; };
void Func2(std::ostream &ostr) { ostr << "F2" << std::endl; };
};
class DerClass : public MyClass {
int index;
public:
virtual void Print(std::ostream &ostr) override
{
print(ostr, &DerClass::Func1, &DerClass::Func3);
}
void Func3(std::ostream &ostr) { ostr << "F3" << index << std::endl; };
};
int main()
{
MyClass cl1;
cl1.Print(std::cout);
DerClass cl2;
cl2.Print(std::cout);
}
如果"各种东西"one_answers"其他东西"是不同的,你可以使这些部分虚拟。
但是你不能在基类中调用子类的成员函数,所有的函数都需要具有相同的类型。
一个建议可能是间接通过自由函数。
class MyClass;
typedef void (*Printer)(MyClass*, std::ostream&);
class MyClass {
std::string name;
public:
MyClass();
void Func1(std::ostream &ostr) { ostr << "F1" << name << std::endl; };
void Func2(std::ostream &ostr) { ostr << "F2" << std::endl; };
void Print(std::ostream &ostr);
protected:
MyClass(Printer* ps) : myprinters(ps) {}
virtual void PrePrint() { /* Various stuff... */ }
virtual void PostPrint() { /* Other stuff... */ }
private:
Printer* myprinters;
};
void MyFunc1(MyClass* obj, std::ostream& os) { obj->Func1(os); }
void MyFunc2(MyClass* obj, std::ostream& os) { obj->Func2(os); }
Printer myclassprinters[] = {
&MyFunc1,
&MyFunc2,
NULL
};
MyClass::MyClass()
: myprinters(myclassprinters)
{
}
void MyClass::Print(std::ostream &ostr)
{
PrePrint();
int i = 0;
for (Printer *fp = myprinters; *fp; fp++, i++) {
std::cerr << "Calling function " << i << std::endl;
(*fp)(this, ostr);
std::cerr << "Called function " << i << std::endl;
}
PostPrint();
}
class DerClass: public MyClass {
public:
DerClass();
void Func3(std::ostream &ostr) { ostr << "F3" << index << std::endl; };
protected:
void PrePrint() { /* More stuff... */ }
};
// C-cast for conciseness only. Use something safer in the real world.
void DerFunc(MyClass* obj, std::ostream& ostr) { ((DerClass*)obj)->Func3(ostr); }
Printer derclassprinters[] = {
&MyFunc1,
&DerFunc,
NULL
};
DerClass::DerClass()
: MyClass(derclassprinters)
{
}
为每个实例使用一个指针成员——我假设您不想为每个实例存储整个函数表。