std::dynamic_pointer_cast successful call on non initialized class

时间:2015-09-09 09:08:20

标签: c++ dynamic casting smart-pointers

I wrote a minimal example to test some behaviour. I tried to get std::dynamic_pointer_cast to fail but encountered unexpected behaviour.

Here is the minimal example that I used:

//virtual_ipsum.h
class virtual_ipsum
{
public:
    virtual_ipsum() { }
    virtual ~virtual_ipsum() { }
};
//derived_lorem.h
#include "virtual_ipsum.h"
#include <iostream>
#define UUID_DERIVED_LOREM_RANDOM 2 //rolled it myself
class derived_lorem :
    public virtual_ipsum
{
public:
    derived_lorem(){ }
    ~derived_lorem(){ }
    void o(){ std::cout << "lorem" << std::endl; };
};
//derived_adipiscing.h
#include "virtual_ipsum.h"
#include <iostream>
#define UUID_DERIVED_ADIPISCING_RANDOM 24 //rolled it myself
class derived_adipiscing :
    public virtual_ipsum
{
public:
    derived_adipiscing(){ }
    ~derived_adipiscing(){ }
    void elit(){ std::cout << "donec" << std::endl; };
};
//server.h
#include <memory>
#include "virtual_ipsum.h"
//note that the header of the server can not contain the derived classes.

class server
{
public:
    server() {}
    ~server() {}
    std::shared_ptr<virtual_ipsum> getDerivedClassByUUID(int UUID);
};
//server.cpp
#include "server.h"
#include "derived_lorem.h"
std::shared_ptr<virtual_ipsum> server::getDerivedClassByUUID(int UUID)
{
    // after careful examination of the UUID the
    // server will send the correct derived class
    return std::make_shared<derived_lorem>();
}
//client.h
#include <memory>
#include "server.h"
class client
{
private:
    std::shared_ptr<server> s;
public:
    client(std::shared_ptr<server> s) : s(s){}
    ~client(){}
    void dolor();
    void consectetur();
};
//client.cpp
#include "client.h"
#include "derived_lorem.h"
#include "derived_adipiscing.h"
#include <memory>
void client::dolor()
{
    std::shared_ptr<virtual_ipsum> sit = s->getDerivedClassByUUID(UUID_DERIVED_LOREM_RANDOM);
    std::shared_ptr<derived_lorem> amet = std::dynamic_pointer_cast<derived_lorem>(sit);
    amet->o();
}
void client::consectetur()
{
    std::shared_ptr<virtual_ipsum> felis = s->getDerivedClassByUUID(UUID_DERIVED_LOREM_RANDOM);
    //everything should crash and burn
    std::shared_ptr<derived_adipiscing> mauris = std::dynamic_pointer_cast<derived_adipiscing>(felis);
    mauris->elit();
}
//main.cpp
#include <memory>
#include "server.h"
#include "client.h"

void main()
{
    std::shared_ptr<server> s = std::make_shared<server>();
    std::shared_ptr<client> c = std::make_shared<client>(s);
    c->dolor();
    c->consectetur();
}

The output on my machine is: output of minimal example

c->consectetur();的调用应该失败,因为服务器返回了错误的派生类。相反,演员不仅是成功的,而且如果它是正确的类,也应该像它应该有的那样完成。

如何在投射期间在客户端检测到该问题?

1 个答案:

答案 0 :(得分:1)

正如上述评论所指出的那样:

  • 调用mauris->elit();未定义。
  • std :: shared_ptr可以简单地进行空检查。
  • 虚空主要让人不快

将客户端的实施更改为以下内容可解决此问题。

#include "client.h"
#include "derived_lorem.h"
#include "derived_adipiscing.h"
#include <memory>

void client::dolor()

{
    std::shared_ptr<virtual_ipsum> sit = s->getDerivedClassByUUID(UUID_DERIVED_LOREM_RANDOM);
    std::shared_ptr<derived_lorem> amet = std::dynamic_pointer_cast<derived_lorem>(sit);
    if (amet)
    {
        amet->o();
    }
    else
    {
        std::cout << "amet is null" << std::endl;
    }

}

void client::consectetur()
{
    std::shared_ptr<virtual_ipsum> felis = s->getDerivedClassByUUID(UUID_DERIVED_LOREM_RANDOM);
    //everything should crash and burn
    std::shared_ptr<derived_adipiscing> mauris = std::dynamic_pointer_cast<derived_adipiscing>(felis);

    if (mauris)
    {
        mauris->elit();
    }
    else
    {
        std::cout << "mauris is null" << std::endl;
    }
}

新输出: enter image description here