4

我想制作一个多线程模型,其中服务器主循环不会被挂起的数据库事务停止。所以我做了几个简单的类,这是一个非常简化的版本:

enum Type
{
    QueryType_FindUser      = 1 << 0,
    QueryType_RegisterUser  = 1 << 1,
    QueryType_UpdateUser    = 1 << 2,
    //lots lots and lots of more types
};

class Base
{       
public:
    Type type;
};
class User: public Base
{   
public:
    std::string username;
    User(std::string username)
        :username(username)
    {type = QueryType_FindUser;}        
};

现在,当我将数据传输为 时Base,我想再次将其转换回User类:

concurrency::concurrent_queue<QueryInformation::Base> BackgroundQueryQueue;
void BackgroundQueryWorker::Worker()
{
    while(ServerRunning)
    {
        QueryInformation::Base Temp;
        if(BackgroundQueryQueue.try_pop(Temp))
        {
            switch(Temp.type)
            {
                case QueryInformation::Type::QueryType_FindUser:
                {
                    QueryInformation::User ToFind(static_cast<QueryInformation::User>(Temp));//error here
                    //do sql query with user information
                    break;
                }
                //etc
            }
        }
        boost::this_thread::sleep(boost::posix_time::milliseconds(SleepTime));
    }
}

我在哪里标记了//errorhere它说没有用户定义的从Baseto转换的行User,我该怎么办?如何定义这种转换?

我是多态性的新手,所以额外解释一下为什么它不能编译也很好:) 根据我对多态性的理解,应该可以在 base<->derived..

4

2 回答 2

4

您只能通过使用指针引用来使用多态性,而不是直接值。

因此,您应该使用:

QueryInformation::User * user = static_cast<QueryInformation::User *>(&Temp);

并相应地修改您的代码以使用指针而不是直接值。

此外,您分配的方式Temp确实是 class Base,而不是 class User,因此它的“类型”不会是QueryType_FindUser,然后static_cast不会被执行(您不会输入case值)。

多态的正常使用static_cast应该是这样的:

QueryInformation::Base * temp = new QueryInformation::User; 
// or obtain by some other methods, so that you don't know the exact
// type, but anyway you *must* use a pointer (or reference).

switch(temp->type)
{
case QueryInformation::Type::QueryType_FindUser:
    {
        QueryInformation::User * user = static_cast<QueryInformation::User*>(temp);
    }
}

在你的情况下,这意味着而不是:

concurrency::concurrent_queue<QueryInformation::Base> BackgroundQueryQueue;

你应该有(注意指针):

concurrency::concurrent_queue<QueryInformation::Base *> BackgroundQueryQueue;

正如 Mats 所建议的那样,调用一个虚拟方法可能会更好,Base它会自动进行调度,而不是自己创建 aswitch并手动制作 a static_cast

于 2013-07-05T09:32:48.253 回答
1

对我来说,这似乎有点不对劲。

首先,您的数据结构concurrent_queue<QueryInformation::Base>正在存储Base对象,这意味着实际对象(例如User)中的任何附加信息都将由于切片而丢失。您需要使用(智能)指针来存储Base对象的地址 - 然后它将能够保存任何大小的对象。

其次,当然,这应该使用虚函数来完成所需的任务。如果您存储它是什么类型的对象,然后调用dynamic_cast转换该对象,这是“错误的”。当然,在极少数情况下这是正确的做法,但大多数情况下,dynamic_cast(或static_cast)在一个对象和另一个对象之间转换是一种“难闻的气味”,您可能知道,应该避免难闻的气味.

于 2013-07-05T09:33:24.887 回答