2013-03-15 3 views
2

У меня есть struct A, который имеет несколько конструкторов с разными членами данных, инициализированных.Ошибка при вызове конструктора из другого конструктора в C++

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. В чем проблема?

+0

Какой компилятор и опции? Похоже, вы не используете C++ 11, даже если вы намеревались. –

+0

Возможно, ваш компилятор не поддерживает делегирование конструкторов. Какой компилятор и версия вы используете? – juanchopanza

+0

Я использую 'g ++ -std = C++ 0x', если это то, что вы имеете в виду? И версия 4.6 – user592748

ответ

7

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

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); } 
+3

Вот и все: «Если идентификатор mem-initializer-id обозначает класс конструктора, он должен быть единственным mem -initializer, конструктор является конструктором делегирования, а конструктор, выбранный mem-инициализатором, является целевым конструктором ». от 15.6.2p6 –

+1

Сообщение об ошибке написано ужасно. –

+0

И эта проблема заключается в том, что обычно лучше иметь конструкторы с меньшим количеством делегатов параметров для конструкторов с большим количеством; делегировать все на самый общий конструктор, а специализированные конструкторы будут выполнять свою работу, просто отправив значения по умолчанию в более общий конструктор. – bames53

0

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

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

Операторы, объявляющие 'ccc' и' cccc', не смогли бы инициализировать исходный объект 'CComplex', как, например, конструктор делегирования. – aschepler

+0

как это связано с вопросом? .. В любом случае это не отличается от вызова другой версии перегруженной функции изнутри функции (или даже той же) – SomeWittyUsername

+0

Я хотел показать, что по-прежнему можно позвонить другая версия конструктора. возможно – 4pie0

1

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, {}) {} 
}; 
+0

Интересно. Спасибо за решение. Я бы назвал это ответом, но, думаю, было бы грубо отменить другое. – user592748

+0

Что означает '{}' вместо дополнительных аргументов? – user592748

+1

@ user592748 - это единый синтаксис инициализации значений по умолчанию для этих аргументов. – bames53

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

  • Нет связанных вопросов^_^