这是工作代码,我想简化它的调用。让我们从调用开始:
Config c2( {
new ConfigPairInt( "one", 1 ),
new ConfigPairDouble( "two", 2.0 ),
new ConfigPairString( "three", "3" )
} );
我要摆脱的第一件事是new
。(如果我这样做,new
我想那是内存泄漏了吗?)但是,当我使Config
的构造函数接受vector<ConfigPair&>
并删除这些时new
,我得到的错误页面对我来说没有意义。
我想摆脱的第二件事是类型类名称。如果我改用花括号初始化器,那么编译器确实知道braced-initializer列表是ConfigPair*
,因此它看到的所有内容都应该是ConfigPair
其子类之一的初始化器。但是,编译器实际上是否在搜索子类构造函数?显然不是。(我确实有一个想法,就是让ConfigPair完成其所有子类的工作,并为其提供三个不同的构造函数。它不再是多态的。而且不再是多态的,那么我也可以摆脱这个问题,new
因为向量可能属于此类,ConfigPair
而不是ConfigPair*
由于多态性而需要。但是,多态性似乎完全适合该问题,因此我不愿放弃它。)
我要摆脱的第三件事是vector
初始化程序周围的花括号。我想我可以使用参数包来做到这一点,但是我无法获得子类参数的结果列表来初始化向量。
class ConfigPair {
public:
ConfigPair( const char* pszName_in ) :
pszName( newstring( pszName_in ) )
{
};
virtual ~ConfigPair() {
free( (char*) pszName );
};
const char* pszName;
};
class Config {
public:
Config( std::vector<ConfigPair*> apcpair )
{
for( ConfigPair* pcpair: apcpair )
// do something
}
};
class ConfigPairInt : public ConfigPair {
public:
ConfigPairInt( const char* pszName_in, int iValue_in ) :
ConfigPair( pszName_in ),
iValue( iValue_in )
{
};
int iValue;
};
class ConfigPairDouble : public ConfigPair {
public:
ConfigPairDouble( const char* pszName_in, double dValue_in ) :
ConfigPair( pszName_in ),
dValue( dValue_in )
{
};
double dValue;
};
class ConfigPairString : public ConfigPair {
public:
ConfigPairString( const char* pszName_in, const char* pszValue_in ) :
ConfigPair( pszName_in ),
pszValue( newstring( pszValue_in ) )
{
};
virtual ~ConfigPairString() {
free( (char*) pszValue );
};
const char* pszValue;
};
AS Remy和Panta在其他答案中指出:如果您想使用多态性,就无法摆脱派生的类型名称,因为编译器需要知道要创建的类型。由于这是呼叫者最打字的方式,因此消除它是优先事项。因此,排除了多态性。
取而代之的是,原来用于不同种类对的虚拟基类现在变成了“瑞士军刀”,能够完成其子类的工作。它具有各种构造函数,并且增加了枚举的开销,该枚举要知道调用了哪个构造函数。
public:
ConfigPair( const char* pszName_in, int iValue_in ) {
cfgpair.type = TypeInt64;
cfgpair.pszName = newstring( pszName_in );
cfgpair.u.i = iValue_in;
}
ConfigPair( const char* pszName_in, double dValue_in ) {
cfgpair.type = TypeDouble;
cfgpair.pszName = newstring( pszName_in );
cfgpair.u.d = dValue_in;
}
ConfigPair( const char* pszName_in, const char* pszValue_in ) {
cfgpair.type = TypeSz;
cfgpair.pszName = newstring( pszName_in );
cfgpair.pszValue = newstring( pszValue_in );
}
既然这ConfigPair
是传递给Config
构造函数的唯一类,则意味着编译器对构造函数的类型要求的了解使其可以在调用时推断出对象类型。因此,省去了类名。
此外,由于阵列内容现在是同质的,我们可以把ConfigPair
的自己变成阵列,而不是(如最初需要)仅存储指针到ConfigPair
子类对象。因此,是新的(或替代性的和非内存泄漏的,但更冗长的shared_pointer<ConfigPairXXX>()
表示法)。
Config( const char* pszName_in, // name only used for debugging messages
std::vector<ConfigPair> acpair ) :
Config( pszName_in )
{
for ( const ConfigPair cpair: acpair )
cpair.Set( this );
}
对于呼叫者:
Config c2( { { "one", 1 },
{ "two", 2.0 },
{ "three", "3" } } );
最后,将大括号括起来的初始化列表留在了外面。我探索了用参数包替换向量的方法,但是后来我不知道如何使编译器再知道类型了,因此再次需要该类型。要继续进行此操作,就调用方的简单性而言,将向前退了十步,因此我毕竟坚持使用braced-initializer-list。(如果还有其他替代方法可以在不需要类名的情况下摆脱这些大括号,请让我知道。)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句