2013-04-04 6 views
0

Итак, у меня довольно простой набор шаблонов, которые я хочу использовать вместе, но компилятор продолжает говорить мне, что B :: a имеет неполный тип. Все вперед объявлено, но она по-прежнему не работает ...Шаблоны, вызывающие функции друг друга

#include <iostream> 

using namespace std; 

template <typename T> class A; 
template <typename T> class B; 

template <typename T> 
class A{ 
public: 
    void ATestFunction(); 
    void CallBFunction(); 
protected: 
    B<T> b; 
}; 

template <typename T> 
class B{ 
public: 
    void BTestFunction(); 
    void CallAFunction(); 

protected: 
    A<T> a; 
}; 

template <typename T> 
void A<T>::ATestFunction(){ 
    cout << "A was used for a function call" << endl; 
} 

template <typename T> 
void B<T>::BTestFunction(){ 
    cout << "B was used for a function call" << endl; 
} 


template <typename T> 
void A<T>::CallBFunction(){ 
    b.BTestFunction(); 
} 

template <typename T> 
void B<T>::CallAFunction(){ 
    a.ATestFunction(); 
} 

int main() 
{ 
    A<int> dragons; 
    dragons.CallBFunction(); 
    return 0; 
} 

Я спрашиваю это потому, что я столкнулся с некоторыми трудностями программирования некоторых классов типа массива, которые зависят друг от друга (реализаций двухмерного массива, который может доступ к ним можно получить следующим образом: [] []), но эта проблема возникла и бросила шестерню в работах. Я сделал эту программу тестирования, но она все еще терпит неудачу. Я пробовал как MinGW 4.7.2, так и GNU g ++ в Linux, и каждый из них дал мне ту же проблему.

ответ

5

Ядро вопроса можно увидеть в этой части кода:

template <typename T> 
class A{ 
    B<T> b; 
}; 

template <typename T> 
class B{ 
    A<T> a; 
}; 

С ++ является языком с семантикой значений, что означает, что B<T> b; представляет собой объект типа B<T> (а не в качестве ссылки, как в Java или C# со ссылочными типами). То есть, A<T>содержит a B<T>. Теперь, если вы посмотрите на определение шаблона B, вы увидите, что в свою очередь он содержит дополнительный объект A<T>. Это практически невозможно, так как A<T> не может содержать объект, который содержит A<T>. Каким будет размер объекта A<T>?

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

0

Даже если вы использовали указатели, это не сработало. Это будет в основном вызвать бесконечный цикл A's и B's создаются

А создает B создает создает B создает ...

это будет работать.

#include <iostream> 

using namespace std; 

template<typename T> class A; 
template<typename T> class B; 

template<typename T> 
class A 
{ 
public: 
    A() 
    { 
     b = new B<T>(this); 
    } 
    A(B<T>* pb) 
    { 
     b = pb; 
    } 
    void ATestFunction() 
    { 
     cout << "A was used for a function call" << endl; 
    } 
    void CallBFunction() 
    { 
     b->BTestFunction(); 
    } 
protected: 
    B<T>* b; 
}; 

template<typename T> 
class B 
{ 
public: 
    B() 
    { 
     a = new A<T>(this); 
    } 
    B(A<T>* pa) 
    { 
     a = pa; 
    } 
    void BTestFunction() 
    { 
     cout << "B was used for a function call" << endl; 
    } 
    void CallAFunction() 
    { 
     a->ATestFunction(); 
    } 

protected: 
    A<T>* a; 
}; 

int main() 
{ 
    A<int> dragons; 
    dragons.CallBFunction(); 

    B<int> bdragons; 
    bdragons.CallAFunction(); 
    return 0; 
} 

или, возможно, просто используя статические функции

#include <iostream> 

using namespace std; 

template<typename T> class A; 
template<typename T> class B; 

template<typename T> 
class A 
{ 
public: 
    static void ATestFunction() 
    { 
     cout << "A was used for a function call" << endl; 
    } 
    void CallBFunction(); 

}; 

template<typename T> 
class B 
{ 
public: 
    static void BTestFunction() 
    { 
     cout << "B was used for a function call" << endl; 
    } 
    void CallAFunction(); 

}; 
template<typename T> 
void A<T>::CallBFunction() 
{ 
    B<int>::BTestFunction(); 
} 


template<typename T> 
void B<T>::CallAFunction() 
{ 
    A<int>::ATestFunction(); 
} 

int main() 
{ 
    A<int> dragons; 
    dragons.CallBFunction(); 

    B<int> bdragons; 
    bdragons.CallAFunction(); 
    return 0; 
} 
Смежные вопросы