Кажется, проблема связана с аргументами, принятыми конструктором:
algoContainer( algo1Virtual &alg1,
algo2Virtual &alg2 );
Примечание. Я удалил аргументы по умолчанию для краткости.
это принимает аргументы как неконстантные ссылки. Итак, когда вы делаете звонок, как:
algoContainer myAC(algo1Concrete(workData));
конструкция:
algo1Concrete(workData)
приводит к построению анонимного временного. Анонимные временные пользователи не могут связываться с неконстантными ссылками, просто потому что они являются временными и любые изменения, которые вы можете внести в них, мгновенно исчезнут (это не реальная причина, но, кажется, имеет смысл. Это ничего не значит для изменения анонимного временный, так как у вас нет возможности использовать его позже (без имени) или в конечном итоге (его временно)). На самом деле неконстантные ссылки могут связываться только с l-значениями, а анонимные временные значения являются r-значениями. (Подробности: Неконстантная ссылка может быть привязана только к lvalue )
В общем, этот вид использования означает, что кто-то хочет полностью передать право собственности на конструируемый объект функции. Это может быть сделано либо передачей по значению (дорого), либо в C ++ 11, путем передачи ссылки на rvalue.
Передача по значению будет выглядеть так:
algoContainer( algo1Virtual alg1,
algo2Virtual alg2 );
Это приведет к ненужным копиям.
Другой вариант - передать ссылку на rvalue в C ++ 11, например:
algoContainer( algo1Virtual &&alg1,
algo2Virtual &&alg2 );
Теперь ваше первое использование будет работать из коробки:
std::vector <data> workData;
// fill workData
algoContainer myAC(algo1Concrete(workData));
myAC.someUsefulFunction();
, но при повторном использовании вам нужно будет изменить его так, чтобы ваш объект «перемещался» в конструктор, и algoContainer становится владельцем данных (тогда локальная переменная names является «плохой» и НЕ должна использоваться вообще).
std::vector <data> workData;
// fill workData
algo1Concrete myA1(workData);
algoContainer myAC(std::move(myA1)); //NOTICE THE std::move call.
//myA1 is now a dummy, and unusable as all the internals have gone.
myAC.someUsefulFunction();
Чтобы этот пример работал, вам нужно реализовать конструктор перемещения для algo1Concrete со следующей подписью:
algo1Concrete ( algo1Concrete&& other )
, который просто переведет внутренние данные в текущий и оставит "другое" в неопределенном состоянии. (Подробности: http://msdn.microsoft.com/en-us/library/dd293665.aspx)
ПРИМЕЧАНИЕ. Относительно аргументов по умолчанию.
Я обычно рекомендую избегать использования аргументов по умолчанию для функций, поскольку они приводят к большей путанице, чем к удобству. Все параметры по умолчанию можно «смоделировать», просто перегружая функцию. Таким образом, в вашем случае у вас будет три ctors:
algoContainer(); //This assumes that the args were both the statics
algoContainer( algo1Virtual alg1 ); //This assumes that arg2 was the static.
algoContainer( algo1Virtual alg1, algo2Virtual alg2 ); //This uses both input.
Я согласен, что он более многословный, и не так много компиляторов в настоящее время реализуют наследующие конструкторы, поэтому мы также довольно часто копировали код. Но это изолирует одну из ряда проблем отладки / магической ценности, которые возникают при исследовании проблемы. Но, FWIW, это просто мнение.