如何动态更改 class 成员的 type/typedef?
How to change the type/typedef of a class member dynamicly?
以下问题。我正在从事一个更大的 C++ 项目。该项目有一个中央数据类:mal::FrameAudio
数据 class 如下所示:
class FrameAudio {
public:
typedef Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic> pluginType;
...
const pluginType& getPlug() const;
void setPlug(const pluginType& plugin);
...
现在我想扩展软件的一些功能,这需要不同的 pluginType
在我的情况下我需要:
typedef Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic> pluginType;
如何在不破坏其余代码功能的情况下实现新的数据类型?
继承?我考虑过做这样的事情 FrameAudioFloat: public FrameAudio.但是数据存储在软件中的初始化方式较早,在我的功能之外,据我所知,当指针设置为基 class 时,您只能使用派生 [=39= 的覆盖函数].所以我不能调用 getPlug() 因为它有另一个 return 类型。
模板?我在考虑创建一个模板 class?但是我看到代码经常使用数据存储的 typedef。你会在代码中经常发现这样的东西:
const mal::FrameAudio::pluginType& plugins = aFrame.getPlug();
我什至在其他 classes 的成员定义中发现了 typedef。那么,用新的 typedef 和函数扩展这个 class 最简单的方法是什么?现在,只要我的功能适用于新的 typedef 而其余代码仍适用于旧的,这对我来说就足够了。也许使用 auto 作为 typedef?
我会选择模板。通过将插件类型默认为现有类型,您可以将现有代码转换为基本案例:
template <class PluginType =
Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic
>
class FrameAudio {
public:
typedef PluginType pluginType;
...
const pluginType& getPlug() const;
void setPlug(const pluginType& plugin);
};
因此,当使用 FrameAudio
而不指定模板参数时,它的行为与以前一样,这意味着现有代码和 typedef 都可以工作。此外,您还为新的插件类型提供了专业化:
template <>
class FrameAudio<
Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic>
>
{
public:
using PluginType = Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic>;
// You can even access classes of the base template
// if you want to share implementations
....
};
另一个巧妙的技巧是在幕后交换类型,例如定义
using FrameAudio = FrameAudioG<
Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic>
>;
其中 FrameAudioG
是具有模板化插件类型的通用版本(如上所示)。通过这种方式,新用户可以使用通用界面,其中可以访问两个插件,并且遗留代码可以像以前一样继续工作。
您不能动态更改对象的类型,C++ 不允许这样做。前面说了这么多。
现在,使用模板可能是正确的方法。重点是,您可能无法在保持代码不变的同时更改它,这正是您有效要求的。相反,您可以编写类似的代码,但将 unsigned char
替换为 float
,因为这不会触及现有代码。为了避免实际的代码重复,创建模板是可行的方法:
template <typename scalar> class FrameAudioT
{
// type from the outer class used in the plugin type
typedef Eigen::Matrix<scalar, Eigen::Dynamic, Eigen::Dynamic> pluginType;
// ...other code...
};
// for compatibility with existing code:
typedef FrameAudioT<char> FrameAudio;
从 FrameAudio
class 开始。然后,选择下一个 class,它仍然依赖于遗留的非模板 FrameAudio
类型。一旦不再使用此类型,您可以删除 typedef。
当然,中间可以重构代码。例如,如果您发现您的代码仅使用不依赖于其第一个参数的插件接口的子集,您可以创建一个纯虚拟基class(“接口class” ) 并改用它。细节取决于你的应用,所以很难给出明确的建议。
以下问题。我正在从事一个更大的 C++ 项目。该项目有一个中央数据类:mal::FrameAudio
数据 class 如下所示:
class FrameAudio {
public:
typedef Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic> pluginType;
...
const pluginType& getPlug() const;
void setPlug(const pluginType& plugin);
...
现在我想扩展软件的一些功能,这需要不同的 pluginType
在我的情况下我需要:
typedef Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic> pluginType;
如何在不破坏其余代码功能的情况下实现新的数据类型?
继承?我考虑过做这样的事情 FrameAudioFloat: public FrameAudio.但是数据存储在软件中的初始化方式较早,在我的功能之外,据我所知,当指针设置为基 class 时,您只能使用派生 [=39= 的覆盖函数].所以我不能调用 getPlug() 因为它有另一个 return 类型。
模板?我在考虑创建一个模板 class?但是我看到代码经常使用数据存储的 typedef。你会在代码中经常发现这样的东西:
const mal::FrameAudio::pluginType& plugins = aFrame.getPlug();
我什至在其他 classes 的成员定义中发现了 typedef。那么,用新的 typedef 和函数扩展这个 class 最简单的方法是什么?现在,只要我的功能适用于新的 typedef 而其余代码仍适用于旧的,这对我来说就足够了。也许使用 auto 作为 typedef?
我会选择模板。通过将插件类型默认为现有类型,您可以将现有代码转换为基本案例:
template <class PluginType =
Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic
>
class FrameAudio {
public:
typedef PluginType pluginType;
...
const pluginType& getPlug() const;
void setPlug(const pluginType& plugin);
};
因此,当使用 FrameAudio
而不指定模板参数时,它的行为与以前一样,这意味着现有代码和 typedef 都可以工作。此外,您还为新的插件类型提供了专业化:
template <>
class FrameAudio<
Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic>
>
{
public:
using PluginType = Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic>;
// You can even access classes of the base template
// if you want to share implementations
....
};
另一个巧妙的技巧是在幕后交换类型,例如定义
using FrameAudio = FrameAudioG<
Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic>
>;
其中 FrameAudioG
是具有模板化插件类型的通用版本(如上所示)。通过这种方式,新用户可以使用通用界面,其中可以访问两个插件,并且遗留代码可以像以前一样继续工作。
您不能动态更改对象的类型,C++ 不允许这样做。前面说了这么多。
现在,使用模板可能是正确的方法。重点是,您可能无法在保持代码不变的同时更改它,这正是您有效要求的。相反,您可以编写类似的代码,但将 unsigned char
替换为 float
,因为这不会触及现有代码。为了避免实际的代码重复,创建模板是可行的方法:
template <typename scalar> class FrameAudioT
{
// type from the outer class used in the plugin type
typedef Eigen::Matrix<scalar, Eigen::Dynamic, Eigen::Dynamic> pluginType;
// ...other code...
};
// for compatibility with existing code:
typedef FrameAudioT<char> FrameAudio;
从 FrameAudio
class 开始。然后,选择下一个 class,它仍然依赖于遗留的非模板 FrameAudio
类型。一旦不再使用此类型,您可以删除 typedef。
当然,中间可以重构代码。例如,如果您发现您的代码仅使用不依赖于其第一个参数的插件接口的子集,您可以创建一个纯虚拟基class(“接口class” ) 并改用它。细节取决于你的应用,所以很难给出明确的建议。