变量代表类型?运行时继承?

发布于 2024-11-17 00:25:43 字数 815 浏览 1 评论 0原文

我问这个问题的原因: 我正在使用一个不是我自己设计的大型框架。我需要使用几个与代码无关的“用户信息”类。它们不是从任何公共基类派生的,而且我无权访问源代码来重新编译。

这些信息类的工作方式如下:有类 A、B、C 等。这些类每个都有一个与其关联的信息类 Ainfo、Binfo 等。因为用户(即我)需要将不同的信息附加到给定类的给定对象(这意味着我可能有两个从 Ainfo 派生的不同类,我想将它们附加到 A 的对象),并且只有一个信息槽,我想制作一个可以旧其他各种信息对象的信息对象。这样,我就可以将我的信息添加到这个假信息对象中,该对象是其他信息对象的容器。

问题的出现是因为我想对 Ainfo、Binfo、Cinfo、Dinfo 等执行此操作。所以我想编写一个 mixin 或仅将容器功能添加到任何普通旧信息类中的东西。

问题在于信息类 Ainfo、Binfo 等需要不同的构造函数参数。

所以问题是:

是否可以将类型向量传递到 mixin 的构造函数中?这样我就可以传入适当的构造函数参数的变量列表?您可以将类型分配给模板参数之外的变量吗?你能用这个变量进行转换吗?

或者

是否可以从特定对象继承?例如,我可以使用正确的构造函数创建一个新的 Ainfo 对象,然后对该特定对象进行 mixin 吗?这就像装饰器模式的使用一样,只是我没有通用的接口。 (被装饰的对象是接口)

还是

我必须硬着头皮编写 15,000 个(夸张:))完全相同的类,但继承自不同的基类并包含不同类型的对象?

摘要:

我需要向几个不同的类添加容器功能,同时维护每个类的接口并利用它们的参数构造函数。我不想重复代码。

提前致谢。抱歉完全屠宰术语。

My reason for asking the question:
I am using a large framework not of my own design. I need to use several "user information" classes which are unrelated as far as the code is concerned. They do not derive from any common base class, and I do not have access to the source code to recompile.

These information classes work like this: there are classes A, B, C, etc. These classes each have an information class, Ainfo, Binfo, etc. associated with them. Because the user (i.e. me) needs to attach different informations to a given object of a given class (meaning I might have two different classes deriving from Ainfo that I want to attach to an object of A), and there is only one information slot, I want to make an information object that can old other various information objects. That way, I can just add my information into this fake information-object-which-is-a-container-for-other-information-objects.

The problem arises in that I would like to do this for Ainfo, Binfo, Cinfo, Dinfo etc. So I would like to write a mixin or something that just adds the container functionality to any of the plain old info classes.

The problem is that the information classes Ainfo, Binfo, etc. require different constructor arguments.

So the question:

Is it possible to pass a vector of types into the constructor of the mixin? That way I could have a variable list of appropriate constructor parameters passed in? Can you assign a type to a variable outside of a template argument? Can you cast with this variable?

or

Is it possible to inherit from a specific object? Could I for example create a new Ainfo object using the correct constructor, then do the mixin on that specific object. This would be like the usage of the decorator pattern, except I have no common interface. (the object being decorated is the interface)

or

am I just going to have to bite the bullet and write 15,000 (exaggeration :) ) classes which are exactly the same, but inherit from a different base class and contain a different type of object?

Summary:

I need to add a container feature to several different classes while maintaining the interface of each class and utilizing their argument-taking constructors. I would like to not duplicate code.

Thanks in advance. Sorry for totally butchering terminology.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

长发绾君心 2024-11-24 00:25:43

在我看来,你想要的是 Boost.Variant。它就像 C++ 风格的联合。它是强类型的(以便您始终知道其中实际存储的内容),并且它具有强大的访问机制,可以轻松地将许多不同的类型映射到单个操作。

例如,您可以这样做:

typedef boost::variant<Ainfo, Binfo, Cinfo> CommonInfo;

//In a function.
CommonInfo someInfo = Ainfo();

然后您可以编写可用于调用 info 对象的成员的访问者函子。

class DoThingInfoVisitor : boost::static_visitor<>
{
    void operator()(Ainfo &info) {info.DoThing()}
    void operator()(Binfo &info) {info.DoThing2()}
    void operator()(Cinfo &info) {info.StepA(); info.StepB();}
};

有了这个对象,如果您想要执行此 DoThing 对任何 CommonInfo 类型意味着的任何操作:

CommonInfo someInfo = Ainfo();
boost::apply_visitor( times_two_visitor(), someInfo );

这将调用 Ainfo 版本,因为这正是存储在 中的内容>一些信息。如果它存储了 Binfo,那么您就可以使用它。您可以构建一个包含这些访问者的套件;它们可以返回值、接受参数(尽管您需要将它们存储在函子中)以及您可以从文档中学习的各种其他技巧。

It sounds to me like what you want is a Boost.Variant. It's like a C++-style union. It is strongly typed (so that you always know what you actually stored in it), and it has a powerful visitation mechanism that makes it easy to map many different types to a single operation.

For example, you can do this:

typedef boost::variant<Ainfo, Binfo, Cinfo> CommonInfo;

//In a function.
CommonInfo someInfo = Ainfo();

You can then write visitor functors that can be used to call members of the info objects.

class DoThingInfoVisitor : boost::static_visitor<>
{
    void operator()(Ainfo &info) {info.DoThing()}
    void operator()(Binfo &info) {info.DoThing2()}
    void operator()(Cinfo &info) {info.StepA(); info.StepB();}
};

Armed with this object, if you want to do whatever this DoThing means for any CommonInfo type:

CommonInfo someInfo = Ainfo();
boost::apply_visitor( times_two_visitor(), someInfo );

This will call the Ainfo version, since that's what happens to be stored in someInfo. If it had stored Binfo, then you could use that. You can build a suite of these visitors; they can return values, take parameters (though you'll need to store them in the functor), and various other tricks you can learn from the docs.

余厌 2024-11-24 00:25:43

如果它在模板中不可行,并且您无法使用预处理器破解它,那么您将不得不手动完成。 C++ 在运行时不包含任何类型操作,您所拥有的就是 typeid()dynamic_cast

If it's not doable in templates, and you can't hack it with the preprocessor, then you're gonna have to do it by hand. C++ doesn't contain any type manipulation at run-time, typeid() and dynamic_cast is all you've got.

謌踐踏愛綪 2024-11-24 00:25:43

这可能有点过于简单化,但如果没有其他问题,它应该有助于澄清你的问题。使用模板,您可以轻松生成从信息类派生的类。以下课程说明了这个概念。

class Ainfo {
  std::string _a;
public:
  void setContent(const std::string& A);
  const char * print() const; // prints _a
};

class Binfo {
  std::string _b;
public:
  void setContent(const std::string& B);
  const char * print() const; // prints _b
};

template<class Tinfo>
class Info : public Tinfo {
};

然后您可以按如下方式使用该模板。

Info<Ainfo> my_info;
my_info.setContent("test");
std::cout << my_info.print();

更新:如果您还想覆盖模板的构造函数,请尝试使用成员模板。

template<class Tinfo>
class Info : public Tinfo {
public:
    template<typename arg>
    Info(arg rhs) : Tinfo(rhs) { }
};

使用它,您可以编译并运行以下命令。

Info<Ainfo> my_info("Testing...");
std::cout << my_info.print();

我可能是错的,但我有一种感觉,我们现在已经很接近了......

This may be a bit of an oversimplification, but if nothing else it should help to clarify your question. Using templates, you can easily generate classes that derive from your info classes. The following classes illustrate this concept.

class Ainfo {
  std::string _a;
public:
  void setContent(const std::string& A);
  const char * print() const; // prints _a
};

class Binfo {
  std::string _b;
public:
  void setContent(const std::string& B);
  const char * print() const; // prints _b
};

template<class Tinfo>
class Info : public Tinfo {
};

You could then use this template as follows.

Info<Ainfo> my_info;
my_info.setContent("test");
std::cout << my_info.print();

UPDATE: If you also want to override the template's constructor, try using a member template.

template<class Tinfo>
class Info : public Tinfo {
public:
    template<typename arg>
    Info(arg rhs) : Tinfo(rhs) { }
};

Using this, you can compile and run the following.

Info<Ainfo> my_info("Testing...");
std::cout << my_info.print();

I could be wrong, but I have a feeling that we're getting pretty close now...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文