【发布时间】:2019-04-07 22:21:04
【问题描述】:
我正在寻找 C++ 中缺少虚拟模板函数的解决方法。 我想要的理想是能够将我的派生类存储在一个向量中,遍历它们并调用正确的函数,所以在伪代码中:
template<typename T>
struct Output
{
...
};
struct Base
{
template<typename T>
virtual void doSomething(Output<T>& out) = 0;
};
struct DerivedA : public Base
{
DerivedA(const char* filename) {...}
template<typename T>
void doSomething(Output<T>& out) final
{
...
}
};
struct DerivedB : public Base
{
DerivedB(const char* filename) {...}
template<typename T>
void doSomething(Output<T>& out) final
{
...
}
};
int main()
{
std::vector<Base*> vec;
vec.push_back(new DerivedA("data1.bin"));
vec.push_back(new DerivedB("data2.bin"));
vec.push_back(new DerivedA("data3.bin"));
vec.push_back(new DerivedA("data4.bin"));
Output<float> outF;
Output<double> outD;
Output<int> outI;
for (auto e : vec)
{
e->doSomething(outF);
e->doSomething(outD);
e->doSomething(outI);
}
return 0;
}
如果解决方法尽可能“无痛”且不冗长,我会更喜欢它(因为我使用模板来避免首先为 n 个不同类型重新定义相同的函数 n 次)。我想到的是用 std::map 让自己成为一个 vtable,并做一些 dynamic_casts。我正在寻找任何更好的想法,或者如果您认为它在这种情况下是最好的,甚至可以简洁地实现该想法。我正在寻找一种理想情况下干扰最小的解决方案,并且很容易向其中添加新类。
编辑: 我想出了一个解决方法,但它包含一些冗长(但至少避免了重要的代码重复):
struct Base
{
virtual void doSomething(Output<int>& out) = 0;
virtual void doSomething(Output<float>& out) = 0;
virtual void doSomething(Output<double>& out) = 0;
private:
template<typename T>
void doSomething(Output<T>& out)
{
std::cout << "Base doSomething called with: " << typeid(T).name() << "\n";
}
};
struct DerivedA : public Base
{
void doSomething(Output<int>& out) final
{
doSomething<int>(out);
}
void doSomething(Output<float>& out) final
{
doSomething<float>(out);
}
void doSomething(Output<double>& out) final
{
doSomething<double>(out);
}
private:
template<typename T>
void doSomething(Output<T>& out)
{
std::cout << "DerivedA doSomething called with: " << typeid(T).name() << "\n";
}
};
struct DerivedB : public Base
{
void doSomething(Output<int>& out) final
{
doSomething<int>(out);
}
void doSomething(Output<float>& out) final
{
doSomething<float>(out);
}
void doSomething(Output<double>& out) final
{
doSomething<double>(out);
}
private:
template<typename T>
void doSomething(Output<T>& out)
{
std::cout << "DerivedB doSomething called with: " << typeid(T).name() << "\n";
}
};
有没有人有更好的想法,我可以如何做到这一点,而不必一遍又一遍地重新定义相同的功能?理想情况下,它会在基类中定义一次,CRTP 似乎没有帮助。动态转换似乎是另一个明智的选择。
【问题讨论】:
-
@bipll 你能详细说明一下吗?我通读了解释,但它适用于不同的类,而不是函数。我的模板不在课堂上,而是在功能上。概述的用例似乎也不同意我正在做的事情。我基本上是在尝试避免代码重复,同时拥有虚拟功能。我可以很好地定义 doSomethingFloat、doSomethingInt、doSomethingDouble 并使用虚函数,但是我每次都必须在 3 个不同的地方修改代码。宏可以做,但看起来不优雅。
-
@NellieDanielyan 并没有真正解决我的问题。我不想存储数据。我希望减少代码重复和冗长,请参阅我的第二次编辑(顺便说一句,在你确定它是重复的之前就可以使用它,这让我相信你甚至没有阅读它)。
标签: c++ templates virtual-functions