Visual Studio 2013编译成功但有明显错误

时间:2015-02-20 04:38:26

标签: c++ visual-studio compiler-errors

我正在使用Visual Studio Professional 2013.我有一个相当奇怪的问题。通常人们发布有关收到错误的帖子 - 我在这里发布的关于不会收到错误的帖子。

我写了一个自定义的Matrix类(用于家庭作业)。 我已按如下方式覆盖赋值运算符:

template<typename T>
Matrix<T>& Matrix<T>::operator=(const Matrix<T> &other) {
    if (this != &other) {
        if (this->mRows != other.mRows || this->nColumns != other.nColumns) {
            deleteMatrixArray();
            this->mRows = other.mRows;
            this->nColumns = other.nColumns;
            newMatrixArray();
        } // else reuse the existing array
        // copy contents
        for (unsigned int i = 0; i < this->mRows; i++) {
            for (unsigned int j = 0; j < this->nColumns; j++) {
                this->matrix[i][j] = other.matrix[i][j];
            }
        }
    }
    return *this;
}

我最近更改了newMatrixArray()方法以接受bool参数:

template<typename T>
void Matrix<T>::newMatrixArray(bool init) {
    this->matrix = new T*[this->mRows];
    for (unsigned int i = 0; i < this->mRows; i++) {
        if (init) {
            this->matrix[i] = new T[this->nColumns]();
        } else {
            this->matrix[i] = new T[this->nColumns];
        }
    }
}

但是,Visual Studio仍然可以成功编译......除非

#include "Matrix.h"

int main() {

    Matrix<int> matrix;

    Matrix<int> otherMatrix;
    otherMatrix = matrix;

    return 0;
}

我编写了一些使用重载赋值运算符的代码。 这让我很担心,因为现在我不知道还有什么可以被打破,Visual Studio也没有告诉我!

这是怎么回事?

更多信息:
如您所见,我正在使用模板。所有Matrix代码都在Matrix.h文件中 - 声明后跟定义。使用模板时需要这样做。除了main.cpp文件之外,Matrix类是我项目中现在唯一的类。我检查并确保声明和定义匹配。

信用:Praetorian
编辑:(解决方案)
您可以使用:

template class NameOfClass<NameOfType>;

针对特定类型编译模板类。

您也可以使用:

template ReturnType NameOfFunction(Args ... );

使用模板参数编译类外的方法。

这些应放在全球范围内。

3 个答案:

答案 0 :(得分:1)

你说:

  

这令我担心,因为现在我不知道还有什么可以被打破,Visual Studio也没有告诉我!

     

这是怎么回事?

编译器正在做什么没有错。如果未使用类模板的成员函数,则该函数不会被实例化。无论函数是否被实例化,都会报告一些错误,例如不匹配的括号,但是除非函数被实例化,否则会报告其他错误,例如您提到的错误。

答案 1 :(得分:0)

如果未使用模板中的某些内容,则不会(完全)解析它,也不会发出错误。
它几乎必须是这样的,这不是一个VS错误,它的符合行为。
考虑:

template<typename T>
class X
{
public:
    void work_always(const T&) {}
    void requires_copyable(T) {}
};

如果你在一个不可复制的类型上实例化它,它应该仍然可以工作,只要你 仅使用work_always

标准库甚至使用它,例如vector resize,即 要求T为
默认可构造,但vector仍可用于不是的类型, 只要你 不要求任何需要它的方法。

当然,这使得模板测试有点困难,你必须确保使用所有内容。

答案 2 :(得分:0)

标准基本上要求在申报时执行大多数检查。只有那些不能执行的检查才会推迟到实例化时间。后面的检查涉及依赖名称。有关详细说明,请参阅here

由于newMatrixArray是依赖的,因此在实例化时间之前不会检查它。如果从未使用过成员函数,则不会实例化它。

此规则的原因是,在知道模板参数之前,尚未完全了解从属名称的含义。

(至少某些版本的)MSVC的问题是在实例化时间之前甚至不检查非依赖名称。您可以尝试编译this program以检查编译器是否受到影响。如果它编译,则存在错误。