2017-02-18 20 views
-3

Рассмотрим следующие классы:shared_ptr с несколькими интерфейсами

class MyInterface1 { 
    ... 
}; 
class MyInterface2 { 
    ... 
}; 
class MyClass : public MyInterface1, public MyInterface2 { 
    ... 
}; 

Если у меня есть следующий код:

void MyFunction(shared_ptr<MyInterface1>& out); // returns a make_shared<MyClass> 

shared_ptr<MyInterface1> c1; 
shared_ptr<MyInterface2> c2; 
MyFunction(c1); 
c2 = c1; 

Я не могу назначить c2 для c1.

Кроме того, он также не будет компилироваться, если я просто позвоню MyFunction(c2), что я ожидал бы работать, так как MyClass происходит от MyInterface1 и MyInterface2. Это похоже на ошибку компилятора (обновление Visual Studio 2015 Update 3), которая может стоить обмена. Может ли кто-нибудь воспроизвести это?

+4

Нет, это не ошибка компилятора. –

+5

Это не имеет никакого отношения к 'shared_ptr', это также не работает с необработанными указателями. – tkausl

+1

'MyClass' может быть' MyInterface1' или 'MyInterface2', но между MyInterface1 и MyInterface2 нет никакой связи. – user4581301

ответ

-5

Вы можете сделать это с помощью необработанных указателей, но это невозможно сделать с shared_ptr. Не используйте shared_ptr, но вместо этого сделайте следующее:

void MyFunction(MyInterface1* out); // returns a new MyClass() 

MyInterface1* c1; 
MyInterface2* c2; 
MyFunction(c1); 
c2 = (MyInterface2*)c1; 
MyFunction((MyInterface1*)c2); 

Это, безусловно, намного чище, проще и удобнее обслуживать. Кроме того, это быстрее, поскольку вы больше не используете shared_ptr и имеете меньше накладных расходов. Не используйте shared_ptr, если вы заботитесь о производительности.

+0

Не лучший выбор по нескольким причинам. Избегайте кастинга C-стиля - это может повредить вам плохо. Возвращение нового объекта через аргумент с указателем без явного владения в большинстве случаев является другой плохой идеей. – Dusteh

+1

Действительно плохой совет, чувак. C-style cast похож на Бога: «Поверь мне, я знаю, что делаю». Лучше надеюсь, что Бог прав, потому что это произойдет правильно или неправильно. В этом случае вы играете Бога, и вы ошибаетесь. – user4581301

+0

Я единственный человек, который действительно предложил решение, и все остальные говорят о своей плохой идее. Если его плохая идея возьмет его с создателем языка. Это не вопрос о стиле, так что возьмите свою «святую войну» в другом месте ... Разработчик задал вопрос, и я был единственным человеком, который действительно дал ответ, а все остальные просто комментировали жалобы и не имели никакой ценной проницательности ... Нет У людей возникает проблема с сообществом. –

4

MyInterface1 и MyInterface2 - полностью несвязанные типы. Просто потому, что объект, на который указывает c1 имеет тип выполнения, который унаследован от обоих, статические типы несовместимы, и вы должны будете использовать бросок, чтобы назначить одну на другую

shared_ptr<MyInterface1> c1; 
shared_ptr<MyInterface2> c2; 
MyFunction(c1); 
c2 = dynamic_pointer_cast<MyInterface2>(c1); 

Live Example

Это будет , конечно, работает только в том случае, если фактический динамический тип *c1 наследуется от MyInterface2. Как и любые dynamic_cast, dynamic_pointer_cast вернет nullptr, если типы несовместимы.