C++类声明和命名空间

Sve*_*end 0 c++ templates namespaces class header-files

我正在尝试编写一个C++库的问题.这是通常的设置,一个cpp文件,一个头文件.我希望头文件只显示要使用的部分(例如,我有一个抽象基类,我不想在头文件中).到目前为止,我只是处理一个文件(我认为这应该没有区别,因为包含是由预处理器完成的,它不关心任何事情).

您会注意到"头文件"分布在头部实现文件之前和之后的两个位置.

#include <stdio.h>

// lib.h
namespace foo {
    template <class T> class A;
}

// lib.cpp
namespace foo {
    template <class T> class A {
        private:
        T i;
        public:
        A(T i) {
            this->i = i;
        }

        T returnT() {
            return i;
        }
    };
};

// lib.h
namespace foo {
    template <class T> T A<T>::returnT();
}

// foo.cpp
void main() {
    foo::A<int> a = foo::A<int>(42);
    printf("a = %d",a.returnT());
}
Run Code Online (Sandbox Code Playgroud)

所以,当然,我希望我的头文件只包含

namespace foo {
    template <class T> class A;
    template <class T> T A<T>::returnT();
}
Run Code Online (Sandbox Code Playgroud)

但是我的编译器不喜欢这个(它抱怨它returnT不是成员foo::A<T>.我不想把类声明本身放在标题中的原因是它会(根据我的理解),包含所有的私有和类似的东西,我想隐藏.

也许只是我,但是下面的头文件似乎"糟糕",至少作为"接口规范".它暴露了一些Alib的用户不需要知道的内部结构.

// lib.h
namespace foo {
    template <class T> class A {
        private:
        int i;
        public:
        A(T);
        T returnT();
    };
}

// lib.cpp
namespace foo {
    template <class T> A<T>::A(T i) {
        this->i = i;
    }
    template <class T> T A<T>::returnT() {
        return i;
    }
};
Run Code Online (Sandbox Code Playgroud)

这是接受的做法吗?如果可能的话,我想要一个更抽象的头文件.

Jam*_*lis 5

您不能将模板的定义与其声明分开.他们都必须一起进入头文件.

因为"为什么?" 我建议阅读"为什么我不能将模板类的定义与其声明分开并将其放在.cpp文件中?" .


我可能误读了你的问题.要解决可能也是您的问题,这是无效的:

namespace foo {
    template <class T> class A;     
    template <class T> T A<T>::returnT(); 
} 
Run Code Online (Sandbox Code Playgroud)

由于这是无效的相同原因,它无效:

namespace foo {
    class A;
    int A::returnT();
} 
Run Code Online (Sandbox Code Playgroud)

必须在类的定义中声明成员函数.