使用 boost::shared_ptr 的集合中的不同模板类

发布于 2024-12-08 10:05:39 字数 2013 浏览 0 评论 0原文

我有一些设计问题,我想你们中的一个人可能有一些线索可以帮助我。

我试图将我的问题总结为这个简单的例子:

我有两个不同的类 DerivedOneDerivedTwo ,它们继承自同一个 Base 类并共享方法的定义。
我有一组指向 clientshared_ptr,其中有一个来自两个不同类 DerivedOneDerivedTwo 的对象。
因为我不想使用 Base* 指针来保存这两个不同的类,所以我尝试制作客户端类模板。

但我有 2 个不同的班级,我无法将它们放在同一组中。
我认为 shared_ptr 可以在不指定模板参数的情况下保存对象指针,但我错了,或者我不知道该怎么做。

我看到的另一个解决方案是将这 2 个不同的 client 分成 2 个不同的 set

提前感谢您的任何建议。

这是代码:

#include <iostream>
#include <set>
#include <boost/shared_ptr.hpp>

class Base
{
    public:
        virtual void test() = 0;
};

class Derived_one
    : public Base
{
    public:
        void test() {
            std::cout << "Derived One" << std::endl;
        }            
};

class Derived_two
    : public Base
{
    public:
        void test() {
            std::cout << "Derived Two" << std::endl;
        }
};

template <class temp_arg>
class Client
{
    public:        
        int test(){
            obj_.test();
        }

    protected:
        temp_arg obj_;

};

typedef Client<Derived_one> ClientOne;
typedef Client<Derived_two> ClientTwo;    

/// Here I don't want to specify any of the two previously declared client :
//typedef boost::shared_ptr<Client> Client_ptr;
typedef boost::shared_ptr<ClientOne> Client_ptr;

int main(int, const char**)
{
    std::set<Client_ptr> Clients_;
    Client_ptr client_(new ClientOne());

    Clients_.insert(client_);
    client_->test();

    return 0;
}

如果你想看看真正的代码:
https://github.com/gravitezero/Node/tree/experimental/src
Client对应connection
Base 类是 message
两个派生类是 peplyrequest

I have some design problems, I thought one of you might have some clue to help me.

I tried to summarize my problem to this simple example :

I have two different class DerivedOne and DerivedTwo which inherit from the same Base class and share the definition of a method.
I have a set of shared_ptr pointing to client, which have one object from two different class DerivedOne and DerivedTwo.
Because I don't want to use a Base* pointer to hold this 2 different class, I tried to make the client class template.

But I have 2 different class, and I can't hold them in the same set.
I thought shared_ptr could hold an object pointer without specifying the template argument, but I was wrong, or I don't know how to do.

The other solution I see, is to separate those 2 different client in 2 different set

Thanks in advance for any suggestions.

Here is the code :

#include <iostream>
#include <set>
#include <boost/shared_ptr.hpp>

class Base
{
    public:
        virtual void test() = 0;
};

class Derived_one
    : public Base
{
    public:
        void test() {
            std::cout << "Derived One" << std::endl;
        }            
};

class Derived_two
    : public Base
{
    public:
        void test() {
            std::cout << "Derived Two" << std::endl;
        }
};

template <class temp_arg>
class Client
{
    public:        
        int test(){
            obj_.test();
        }

    protected:
        temp_arg obj_;

};

typedef Client<Derived_one> ClientOne;
typedef Client<Derived_two> ClientTwo;    

/// Here I don't want to specify any of the two previously declared client :
//typedef boost::shared_ptr<Client> Client_ptr;
typedef boost::shared_ptr<ClientOne> Client_ptr;

int main(int, const char**)
{
    std::set<Client_ptr> Clients_;
    Client_ptr client_(new ClientOne());

    Clients_.insert(client_);
    client_->test();

    return 0;
}

If you want to give a look to the real code :
https://github.com/gravitezero/Node/tree/experimental/src
Client correspond to connection
The Base class is message
The two derived class are peply and request.

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

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

发布评论

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

评论(2

北渚 2024-12-15 10:05:39

boost 共享模板指针不会执行任何常规指针无法执行的操作(即将两种不同类型放入同一集合中)。每当使用模板时,您都必须显式声明模板参数,因为模板所做的只是在编译时为您生成重复的代码。因此,当您使用模板时,编译器只需重复模板文件的次数,次数与您使用模板参数声明的次数相同。没有模板参数,没有重复,没有模板。至少这是我的理解,我相信如果我错了,C++ 警察会纠正我。

因此,将两种不同类型放入同一个集合中的方法是屏蔽放入集合中的值。执行此操作的最基本方法(也是不好的方法)是创建 void 指针集合,然后根据上下文进行插入和提取。这是危险的,因为这样您将通过指针访问内存,而不检查指针是否指向正确的内存量/格式(这是类型检查)。

所以真正的方法是像 pmr 建议的那样。使您的集合成为基类型指针的集合,并在从列表中插入和提取时使用动态转换在类型之间进行转换。动态转换将在运行时进行检查,以确保您要转换的类型是兼容的。 IE 如果您从 Derived1 投射到 Base,然后再从 Base 投射到 Derived1,这是可以的。如果您从 Derived1 转换为 Base,然后在指向同一内存的指针上从 Base 转换为 Derived2,则这将在运行时失败,因为 Derived2 和 Derived1 不兼容。

这个解释有点长,因为几个月前我也遇到了同样的设计问题,直到我做了一些阅读。

The boost shared template pointers wont perform any magic that you can't do without regular pointers (namely putting two different types into the same collection). Whenever using a template you must explicitly declare the template arguments, because alls a template does is generate duplicate code for you at compile time. So when you use a template, the compiler simply duplicates the template file as many times as you have declared it with the template arguments. No template arguments, no duplication, no template. At least this is my understanding, I'm sure the C++ Police will correct me if I'm wrong.

So the way to put two different types into the same collection is to mask the value being placed in the collection. The most basic way of doing this (and bad way) is to make your collection of void pointers and then cast on insert and extraction depending on the context. This is dangerous, because then you will be accessing memory through the pointer without checking that the pointer points to the correct amount/format of memory (this is type checking).

So the real way to do this is as pmr suggested. Make your collection a collection of base type pointers and use dynamic cast to cast between the types when inserting and extracting from the list. A dynamic cast will check at run-time to make sure that the type you are casting from and to are compatible. IE if you cast from Derived1 to Base, and then later from Base to Derived1 this is okay. If you cast from Derived1 to base, and then later from base to Derived2 on a pointer pointing to the same memory, this will fail at run-time, because Derived2 and Derived1 are not compatible.

This explanation is a little long, because I had the same design trouble a few months ago, until I did some reading.

戏舞 2024-12-15 10:05:39

为什么不想使用指向 Base 实例的指针?如果您使用运行时多态性,这是唯一的方法。如果您实际上不需要运行时多态性,则虚拟成员函数是错误的选择。

只需使用 boost::scoped_ptr 或(更好)C++11 std::unique_ptr 来在 中保留 base*客户端。

如果您选择放弃运行时多态性,则应该考虑 CRTP 来实现静态多态性。

Why don't you want to use a pointer to a Base instance? If you use runtime-polymorphism this is the only way. If you actually don't need the runtime-polymorphism, virtual member functions are the wrong way to go.

Just use a boost::scoped_ptr or (better) a C++11 std::unique_ptr to keep a base* in Client.

If you choose to abandon the runtime-polymorphism you should look into CRTP to implement static polymorphism.

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