Ошибка при использовании абстрактного класса std::make_shared
Я собираюсь опустить довольно много кода, потому что это довольно большие объекты, и мой вопрос на самом деле касается только операции std::make_shared . У меня есть объект в пространстве имен SYNC, который называется D3D11Shader. Это имеет статическую функцию под названием,
SYNC::D3D11Shader * SYNC::D3D11Shader::CreateInstance(const std::string & s)
который возьмет строковый индекс и вернет указатель на экземпляр шейдера, производного от SYNC::D3D11Shader. В какой-то момент я начал использовать умные указатели для автоматизации их удаления в векторе, который содержал все эти шейдеры. Тем не менее, когда я иду, чтобы сделать это,
std::shared_ptr<SYNC::D3D11Shader> shaderPtr;
// ... verification of index and other initialization happens here
// so i am unable to initialize it in it's constructor
shaderPtr = std::make_shared<SYNC::D3D11Shader>(SYNC::D3D11Shader::CreateShader(shaderName));
ошибки компилятора, говорящие о том, что я пытаюсь создать экземпляр D3D11Shader в этой строке, который является абстрактным классом. Я думал, что все, что сделал make_shared - это вернул экземпляр std::shared_ptr. Функция CreateInstance никогда не пытается создать экземпляр этого класса, только объекты, которые его производят и реализуют. Я не получал эту ошибку до использования этой функции и умных указателей. Кто-нибудь знает, что здесь происходит?
2 ответа
Если вы не можете использовать конструктор shared_ptr
, используйте его reset
Функция-член, чтобы дать ему право собственности на новый объект:
std::shared_ptr<SYNC::D3D11Shader> shaderPtr;
shaderPtr.reset(SYNC::D3D11Shader::CreateShader(shaderName));
Причина make_shared<T>
не подходит для этой ситуации, потому что он создает новый T
, передавая свои аргументы своему конструктору. Однако вы уже сконструировали объект, поэтому вам просто нужно передать право владения вашим общим указателем.
Я настоятельно рекомендую не возвращать необработанный указатель из CreateShader
хоть. Вы полагаетесь на абонента CreateShader
знать, чтобы обернуть это в умный указатель или вызов delete
в теме. Вам лучше вернуть unique_ptr
передать право собственности клиенту, а затем они могут сделать shared_ptr
из этого, если им нравится. Смотрите следующее:
std::unique_ptr<SYNC::D3D11Shader> uniquePtr(SYNC::D3D11Shader::CreateShader(shaderName));
// If you want a shared_ptr:
std::shared_ptr<SYNC::D3D11Shader> sharedPtr(std::move(uniquePtr));
Или просто:
std::shared_ptr<SYNC::D3D11Shader> sharedPtr = SYNC::D3D11Shader::CreateShader(shaderName);
Если вы собираетесь использовать умные указатели, используйте их.:)
Достаточно просто:
shaderPtr.reset(SYNC::D3D11Shader::CreateShader(shaderName));
Вы можете увидеть различные варианты reset
функция-член здесь.