模板调用彼此的功能

时间:2013-04-04 01:08:09

标签: c++ c++11

所以,我有一套相当简单的模板,我想一起使用,但编译器一直告诉我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;
}

我问这个是因为我在编写一些相互依赖的数组类型类时遇到了一些困难(实现了一个可以像这样访问的二维数组:[] []),但是这个问题发生了并且扔了一个齿轮在工作中。我做了这个测试程序,但它仍然失败了。我在Linux上尝试过MinGW 4.7.2和GNU g ++,每个人都给了我同样的问题。

2 个答案:

答案 0 :(得分:5)

问题的核心可以在这段代码中看到:

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

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

C ++是一种具有值语义的语言,这意味着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>;或两者)或引用。但也可能是更深层次的重新设计更有意义。

答案 1 :(得分:0)

即使您使用指针,也无法使用。这基本上会触发A和B的无限循环被创建

A创建B创建A创建B创建A ...

这会奏效。

#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;
}