2015-12-11 2 views
1

У меня есть эти классы:Общий аргумента в списке инициализации конструктора

class A 
{ 
public: 
    A(std::shared_ptr<SomeClass> p); 
private: 
    std::shared_ptr<SomeClass> _p; 
}; 

class B 
{ 
public: 
    B(std::shared_ptr<SomeClass> p); 
private: 
    std::shared_ptr<SomeClass> _p; 
}; 

class Foo 
{ 
public: 
    Foo(); 
private: 
    A _a; 
    B _b; 
}; 

Оба аргумента конструктора из A и B одних и той же ссылки указателя shared_ptr. В этом случае:

  • Как бы лучший способ инициализации Foo?

  • Возможно ли использовать список инициализации в Foo s конструктор?

Я смущен, потому что, так как оба класса нуждается в такой же shared_ptr экземпляре, я бы хранить этот указатель куда-нибудь, и я не думаю, что это возможно, со списками инициализации.

Кроме того, если инициализация происходит в теле конструктора, это означает, что оба A и B должны иметь конструктор move, правильно? Потому что я должен был бы сделать что-то вроде этого:

Foo::Foo() //: Cannot use initializer list 
{ 
    auto ptr = std::make_shared<SomeClass>(SomeClass()); 
    _a = A(ptr); 
    _b = B(ptr); 
} 

ответ

2

На самом деле, я думал о лучшем решении. Создайте shared_ptr, а затем делегируйте его частному конструктору, который будет использовать его для построения _a и _b. (Кредит Зан Lynx, предложившее использование параметра функции в качестве временного хранения.)

class Foo { 
public: 
    Foo(): Foo(std::make_shared<SomeClass>()) {} 
private: 
    Foo(std::shared_ptr<SomeClass> ptr): _a(ptr), _b(ptr) {} 
    A _a; 
    B _b; 
}; 
+0

О, спасибо, это хорошее решение: D – lhahn

1

Вы не можете инициализировать элементы в теле конструктора. К тому моменту, когда тело начинает выполняться, члены должны быть уже инициализированы. Следовательно, если вы попытаетесь сделать это, члены будут построены по умолчанию, а затем вы просто назначаете их. A и B не имеют конструкторов по умолчанию, поэтому это не будет компилироваться.

Если вы можете позволить увеличить размер, сделайте shared_ptr членом Foo, а также используйте это.

class Foo { 
public: 
    Foo(): _ptr(std::make_shared<SomeClass>()), _a(_ptr), _b(_ptr) {} 
private: 
    std::shared_ptr<SomeClass> _ptr; 
    A _a; 
    B _b; 
}; 
+2

Я считаю, что вы могли бы также дать Foo() аргумент конструктора по умолчанию и использовать его в качестве хранилища темпа для указателя. –

+0

@ ZanLynx Умный! Хотя, вы просто вдохновили меня на создание еще лучшего решения ... – Brian

1

не Учитывая то, как вы определили классы (т.е. нет возможности доступа к внутренним shared_ptr), я думаю, что ваше решение в порядке. Но обратите внимание, что A и B потребуются конструкторы по умолчанию. Вот как они инициализируются, прежде чем вводить тело конструктора.

Также, как только вы находитесь в корпусе конструктора, вы будете делать назначение. Таким образом, как A, так и B потребуется оператор присваивания.

Кроме того, я считаю хорошей практикой передать std::shared_ptr в функции (включая конструкторы) в качестве ссылок.

Смежные вопросы