我有一个封装在类中的状态机。这是通过依次调用一系列成员函数来完成这些操作来完成的。我也有几个派生类,我想对它们做同样的序列。有没有办法模板化这段代码?
#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);
}
代码运行并且有效,但是我只想编写一次Print例程,而不是每个新类,有没有办法做到这一点,模板?其他课程?
我希望像
这样的东西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'void T :: Print(std :: ostream&amp; str){
答案 0 :(得分:0)
我宁愿把它写成评论,但代码的数量根本不可读。
您可以在下面找到有关如何继承&#34;的可能解决方案。你的Print
。
这应该仅作为建议或提示。特别是printers
的初始化并没有真正完成&#34;一种好的方式&#34;。
希望它能帮助你
#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);
}
编辑:第二种方法
在我看来,这个更漂亮。此外,代码更少,编译器可以对其进行优化:
#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);
}
答案 1 :(得分:0)
如果&#34;各种东西&#34;和其他东西&#34;不同的是,你可以将这些部分虚拟化。
但是你不能在基类中调用子类的成员函数,所有函数都需要具有相同的类型。
一个建议可能是间接通过自由职能。
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)
{
}
这为每个实例使用指针成员 - 我假设你不想为每个实例存储整个函数表。