c ++ 11 — ошибка при вызове конструктора из другого конструктора в переполнении стека

у меня есть struct A у него есть несколько конструкторов с различными инициализированными элементами данных.

template<typename T>
struct A {

typedef std::vector<T> type1
type1 a;
type1 b;
type1 c;

A(type1 i_a): a(i_a) {
}

A(type1 i_a, type1 i_b): A(i_a), b(i_b) {
}

A(type1 i_a, type1 i_b, type1 i_c): A(i_a, i_b), c(i_c) {
}
};

Ошибка, которую я получаю, это когда я ее создаю custom_typeошибка
type A<custom_type> is not direct base of A<custom_type> выделение конструктора, который я вызываю внутри другого конструктора. Я использую C ++ 11. В чем проблема?

2

Решение

Конструктор может инициализировать свои базовые классы и члены, ИЛИ делегировать другому конструктору того же класса, но не обоим.

A(i_a) строит полный A объект, копирующий член a и построение по умолчанию b а также c, Так что не имеет смысла иметь A(type1 i_a, type1 i_b): A(i_a), b(i_b) {} — первый инициализатор уже инициализирован b, Вы могли бы вместо этого иметь

A(type1 i_a, type1 i_b) : A(i_a) { b = std::move(i_b); }
7

Другие решения

Aschepler дает ответ, но я хотел объяснить, что приводит к проблеме, и показать «лучшие практики» для делегирования конструкторов, чтобы избежать ее.

В вашем коде есть ряд конструкторов, каждый из которых более общий, чем конструктор, которому они делегируют. То есть вы пытаетесь делегировать конструктор более специализированному конструктору, который не делает всего, а затем вы выполняете небольшую работу, чтобы справиться с дополнительной общностью. Это отстал от того, что оказалось наиболее практичным способом делегирования конструкции на более ранних языках, которые его поддерживают.

Вместо этого вам нужно, чтобы наиболее общий конструктор был «корнем» делегирования («назначенный инициализатор» или «назначенный конструктор», в других языках). Более специализированные конструкторы будут выполнять свою работу, используя более общие конструкторы, передавая им данные для особого случая, который будет обработан.

В вашем случае специальным поведением является использование значений по умолчанию для некоторых элементов вместо того, чтобы принимать начальные значения от пользователя. Таким образом, ваши более специализированные конструкторы будут выполнять свою работу, передавая параметр, который им дан, вместе со значениями по умолчанию для других членов.

template<typename T>
struct A
{
typedef std::vector<T> type1;
type1 a;
type1 b;
type1 c;

A(type1 i_a, type1 i_b, type1 i_c): a(i_a), b(i_b), c(i_c) {}

A(type1 i_a, type1 i_b): A(i_a, i_b, {}) {}

A(type1 i_a): A(i_a, {}) {}
};
1

но вы все равно можете вызывать разные конструкторы одного и того же класса из тела конструктора (если по какой-то причине вы захотите)

class CComplex{
public:
CComplex(int real1,int image1,char c)
{
cout<<"RealImg";
real=real1;
image=image1;
char* x; char xc=c;x=&xc;
void* v;
f(x);
CComplex ccc(x,v); //this is OK
CComplex cccc(1,2,3); //as this too
}
CComplex():real(0),image(0){cout<<"DEFAULT";}
CComplex(const CComplex &c)
{
real=c.real;
image=c.image;
cout<<"COPY";
}
CComplex& operator=(CComplex const& ref){
cout<<"ASSIGN";
//CComplex* c;
CComplex cobj(43,45,'x');
//c=&cobj;
//CComplex* c=new CComplex(44,45);
return cobj;
}

CComplex(int i1, int i2, int i3){cout<<"\n123!";}
CComplex(const char* y,void* v){cout<<"\nCrefvoid!";}
~CComplex(){cout<<"\n~CComplex(){}";}
public:
void Display(void)
{
cout<<real<<"+"<<image<<"i"<<endl;
}
static bool CComplexComparator(CComplex c1, CComplex c2){return true;}
static void CComplexInit(CComplex& c){
c.real=100;
}
int real,image;
};
0