Я написал минимальный пример для проверки некоторого поведения. Я попытался получить std::dynamic_pointer_cast
сбой, но столкнулся с неожиданным поведением.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();
должен терпеть неудачу, так как сервер возвратил неправильно производный класс. Вместо этого бросок не только успешный, но и завершенный, как если бы он был правильным классом.
Как я могу обнаружить эту проблему на стороне клиента во время кастинга?
, если '' amet' является nullptr' (из-за отказа динамического броска), то это UB. вы можете проверить, не является ли он непустым –
А, я добавил чек для этого, и теперь код обнаруживает его. Благодарю. Является ли выполнение c-> consectetur() неопределенным, и мне просто повезло или он хорошо определен, так как я ввел его в заголовок? – Johannes
Это неопределенное поведение –