std::dynamic_pointer_cast 成功调用非初始化 class
std::dynamic_pointer_cast successful call on non initialized class
我写了一个最小的例子来测试一些行为。我试图让 std::dynamic_pointer_cast
失败,但遇到了意外行为。
这是我使用的最小示例:
//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();
}
我机器上的输出是:
对 c->consectetur();
的调用应该会失败,因为服务器返回了错误的派生 class。取而代之的是,演员表不仅成功而且完成了,如果它是正确的 class.
如何在投射期间在客户端检测到该问题?
正如以上评论所指出的:
- 调用
mauris->elit();
未定义。
- std::shared_ptr 可以简单地进行空检查。
- void main让人不爽
将客户端的实现更改为以下内容可解决问题。
#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;
}
}
新输出:
我写了一个最小的例子来测试一些行为。我试图让 std::dynamic_pointer_cast
失败,但遇到了意外行为。
这是我使用的最小示例:
//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();
}
我机器上的输出是:
对 c->consectetur();
的调用应该会失败,因为服务器返回了错误的派生 class。取而代之的是,演员表不仅成功而且完成了,如果它是正确的 class.
如何在投射期间在客户端检测到该问题?
正如以上评论所指出的:
- 调用
mauris->elit();
未定义。 - std::shared_ptr 可以简单地进行空检查。
- void main让人不爽
将客户端的实现更改为以下内容可解决问题。
#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;
}
}
新输出: