2015-06-03 5 views
2

У меня есть два класса, которые представляют два разных типа данных, которые можно преобразовать взад и вперед. Я хочу, чтобы иметь конструктор для каждого, который принимает объект другого типа, так что я могу легко конвертировать между ними, например, так:C++ взаимозависимые классы

class A{ 
public: 
    A(B n){ 
    //Do stuff converting n to type A 
    } 
}; 

class B{ 
public: 
    B(A n){ 
    //Do stuff converting n to type B 
    } 
}; 

Но это всегда удается собрать.

+0

Это как проблема chicken'n'egg, решения нет. Вам понадобится 'B' для создания' A' и 'A' для создания' B'. –

ответ

3

Если передать B по ссылке, вы можете использовать его в качестве неполного типа в A, с передней декларацией, как:

class B; // forward declaration 

class A { 
public: 
    A() = default; 
    A(B& n); // declare it here 
}; 

class B { 
public: 
    B() = default; 
    B(A n) { 
     //Do stuff converting n to type B 
    } 
}; 

A::A(B& n) // define it here, B is fully visible now 
{ 
    //Do stuff converting n to type A 
} 

int main() 
{ 
    A a; 
    B b(a); 
    A another(b); 
} 

Обратите внимание, что вы также должен конструктор по умолчанию, по крайней мере A или B, так как иначе вы не можете создать A без B или наоборот. Мы также объявили конструктор только в A, но определили его после того, как B полностью виден (спасибо @MattMcNabb за комментарий). Таким образом, вы можете использовать любой член B в конструкторе, так как в этом пункте B полностью виден.

+0

, хотя это и не является строго необходимым, вероятно, также неплохо сделать, чтобы конструкторы преобразования принимали 'B const &' и 'A const &', так как маловероятно, что OP действительно хочет либо скопировать конвертируемый, либо не изменить его –

1

Проблема, с которой вы сталкиваетесь, является общей для начинающих C++ (или C в этом отношении).

Проблема заключается в том, что подпись A(B n) рассматривается компилятором до того, как будет показано объявление B. Но ясно, что вы не можете поставить B до A в код, иначе вы столкнетесь с аналогичным положением.

Это можно решить, используя форвардные декларации и ссылки. Мой предложенный по умолчанию подход к этому вопросу заключается в объявлении этих двух объектов как

class B; 

class A { 
public: 
    A(const B& n) { 
    // Do stuff converting n to type A 
    } 
}; 

class B { 
public: 
    B(const A& n) { 
    // Do stuff converting n to type B 
    } 
}; 
Смежные вопросы