gpt4 book ai didi

派生类中的C++成员函数模板,如何从基类中调用它?

转载 作者:太空狗 更新时间:2023-10-29 22:53:10 27 4
gpt4 key购买 nike

由于我之前的问题听起来令人困惑,我认为最好清楚地说明我想要实现的目标。

我有(暂时忽略继承并关注 X):

class Base {};

class X : public Base {
private:
double m_double;
public:
template<class A> friend
void state( A& a, const X& x ) {
data( a, x.m_double, "m_double" );
}
};

我现在可以引入任意新类,这些类根据数据函数的重载方式执行不同的操作,我们将在下文中将这些称为访问器:

class XmlArchive {...}; //One Accessor
template<class T>
void data( XmlArchive& a, const T& t, const std::string& str ) {
//read data and serialize it to xml Archive
}

class ParameterList {...}; //Another Accessor
template<class T>
void data( ParameterList& a, const T& t, const std::string& str ) {
//put data in a parameter list
}

然后我可以写:

X myX;

XmlArchive myArchive;
state( myArchive, myX );

ParameterList myParameters;
state( myParameters, myX );

太棒了,代码重用! :D 但是以下(显然)失败了:

Base* basePtr = new X; //This would come from factory really, I should not know the type X
state( myParameters, *basePtr ); //Error

目标是使最后一次调用成功。我考虑过的(以及为什么不能接受):

第一个方案:让所有的Accessor都继承自一个共同的基类,比如AccessorBase,然后写在Base中

virtual state( AccessorBase& a ) const = 0;

并在 X 中实现所需的代码(调用状态的语法会略有不同,但可以修复)。问题是 AccessorBase 需要为每种可能的类型都有一个虚函数,它作为数据函数中的第二个参数出现。由于这些类型可以是用户定义的类(参见类组合的情况,X 以 Y 作为数据成员),我不知道如何使这种策略起作用。

第二个选项:在 Base 中为每个访问器创建一个虚函数。这违反了打开/关闭原则,因为添加新的访问器类(例如 TxtArchive)将需要修改基类。

我理解为什么虚拟成员函数不能模板化(不同编译单元中可能有不同的 vtbl)。然而在我看来应该有解决这个问题的方法...... Base 知道它确实是 X 类型,并且 Accessor 的类型总是明确的,所以它是找到一种调用方式的问题(对于XmlArchive 类型的访问器):

state( xmlArchive, x ); //xmlArchive of type XmlArchive, x of type X

这将产生结果。

总而言之,我想打电话:

state( myParameters, *basePtr );

如果 basePtr 指向具有与调用兼容的函数模板的派生类,则成功,否则抛出异常。

在我看来,boost::serialize 做了类似的事情,但我不知道如何(它可能是通过模板在 C++ 中重新实现继承关系,我看到 This() 函数返回最派生的指针但是它变得非常困惑......)

再次感谢您的帮助!

最佳答案

您可以为此使用访问者模式:

class IVisitor
{
public:
virtual void on_data( double, const char * )=0;
virtual void on_data( std::string, const char * )=0;
};

class Base
{
public:
virtual void visit( IVisitor * v )=0;
};

class X : public Base
{
private:
double m_double;
std::string m_string;
public:
void visit( IVisitor * v)
{
v->on_data( m_double, "m_double" );
v->on_data( m_string, "m_string" );
}
};

Base * base = ...;
XmlArchive ar; // This must derive from IVisitor
base->visit(&ar);
ParameterList pl; // This must derive from IVisitor
base->visit(pl);

如果您不喜欢在 IVisitor 中实现每个不同的 on_data 类型,您可以使用 boost::any -但根据我的经验,实现该功能所需的分支是不值得的。

关于派生类中的C++成员函数模板,如何从基类中调用它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2914081/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com