0

我有一个相当标准的情况,我想通过以下方式使用模板类:

  1. 定义一个 .h 文件
  2. 让它包含 .cpp

在我尝试的所有其他编译器(即 g++ 和 clang/llvm)中,这都可以正常工作。在 Visual Studio 中,它告诉我该文件已被定义。

如果我手动将 .cpp 中的文本剪切并粘贴到 .h 文件中,那么一切正常。我的印象是这正是#include应该做的。

我的预感是,Visual Studio 以某种方式不止一次地编译 .cpp 文件(尽管我放置#pragma once在 .h 和 .cpp 文件上)。

发生了什么,如何让我的模板类在 VS 中运行?

代码如下:
.h:

#pragma once
template <class T>
class myVector
{
private:
    void grow();
public:
int size;
int index;
T** words;
void pushBack(T* data);
inline T* operator[](int);
myVector(void);
~myVector(void);
};

#include "myVector.cpp"

.cpp:

#pragma once
#include "stdafx.h"
#include <cstdlib>
#include "myVector.h"
#include <iostream>
using namespace std;

template<class T>
myVector<T>::myVector(void)
{
    this->size = 2000;
    words = new T*[size];
    index=0;
}

template<class T>
void myVector<T>::pushBack(T* input)
{
    if(index<size)
    {
        words[index]=input;
    }
    else
    {
        grow();
        words[index]=input;
    }
    index++;
}

template<class T>
T* myVector<T>::operator[](int i)
{
    return words[i];
}

template<class T>
void myVector<T>::grow()
{
    //cout<<"I grew:"<<endl;
    size*=2;
    words = (T**)realloc(words,size*sizeof(T*));
}

template<class T>
myVector<T>::~myVector(void)
{
    delete[] words;
}    
4

1 回答 1

2

在我看来,您的困惑源于不知道#pragma once翻译单元如何工作。

#pragma once,就像包含守卫一样,防止文件的内容(通常是标题)被多次拉入单个翻译单元。

如果您#include <vector>在多个实现文件中,内容将全部提取,但每个翻译单元仅提取一次。

所以你应该删除#include "myVector.cpp", 因为MSVS会自动编译实现文件,这也是错误的。

请注意,模板定义必须是可见的,因此您需要将它们移动到.h文件中,就像您所做的那样,或者使用您当前的方法,将.cpp文件重命名为类似.impl或什.h至并包含它。

于 2012-05-07T07:13:40.607 回答