Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 2个模板化类的非模板友元函数未定义引用错误_C++_C++14_C++17 - Fatal编程技术网

C++ 2个模板化类的非模板友元函数未定义引用错误

C++ 2个模板化类的非模板友元函数未定义引用错误,c++,c++14,c++17,C++,C++14,C++17,问题陈述: **** Build of configuration Debug for project Matrix_Vector_Multiplication **** **** Internal Builder is used for build **** g++ -oMatrix_Vector_Multiplication.exe Vector.o Matrix_Vector_Multiplication_main.o Matrix_Vector_Multip

问题陈述:

**** Build of configuration Debug for project Matrix_Vector_Multiplication ****

**** Internal Builder is used for build               ****
g++ -oMatrix_Vector_Multiplication.exe Vector.o Matrix_Vector_Multiplication_main.o Matrix_Vector_Multiplication.o
Matrix_Vector_Multiplication_main.o: In function `main':
D:\C++ Eclipse projects\Matrix_Vector_Multiplication\Debug/../Matrix_Vector_Multiplication_main.cpp:25: undefined reference to `multiply(matrix<int>, vectorimp<int>)'
collect2.exe: error: ld returned 1 exit status
Build error occurred, build is stopped
Time consumed: 1741  ms.  
Checked out the avaiable resources  like 
https://isocpp.org/wiki/faq/templates#templates-defn-vs-decl
https://stackoverflow.com/questions/1353973/c-template-linking-error
https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file?rq=1
and few more 
使用2个不同的模板类1个矩阵类和其他1个向量类,并使用1个友元函数,即乘法函数

错误位置

 multiply(matA,p);
in main.cpp 
#pragma once
#include <iostream>
#include<vector>
#include <time.h>
#include <ostream>
#include "Vector.h"
#define LENGTH 3
#define WIDTH  3

//using namespace std;
template <typename T>
class vectorimp;
template <typename T>
class matrix
  {
private:
    T rows ;
    T cols ;
    T g[LENGTH];
    T **mat;

public:
    //Default constructor
    matrix(T rows , T cols);
    ~matrix();
    T **generatematrix(int rows, int cols);
    void populatematrix(T *src, T size);
    void print();
    template<class T>
    friend void multiply(matrix<T> p, vectorimp<T> v);
  };
#include "Matrix_Vector_Multiplication.h"
#include <iostream>
#include "Vector.h"

using namespace std;

int main()
{

      int srcA[]= {2,4,3,1,5,7,0,2,3};
      matrix<int> matA(3,3);
      matA.populatematrix (srcA,9);
      std::vector<std::vector<int> > v{ { 2,4,3 },
        { 5,1,6 },
        { 6,3,2 } };
        vectorimp<int> p;
        p.populate_vector1D(v);
        multiply(matA,p);
        return 0;
}
问题: 由于我使用非模板函数,将arugements作为模板类,所以我得到了一个错误

undefined reference to `multiply(matrix<int>, vectorimp<int>)'
collect2.exe: error: ld returned 1 exit status

我想提出两个建议,首先,在使用模板时将头文件和cpp文件放在一起,其次请查看以下代码行:

vectorimp<T>::~vectorimp(){}
看起来您正在尝试初始化2D向量,但在您的声明中:

int vec[3]
危险的

T vec3D[3][3];
声明这个家伙,但你从未用构造函数初始化过。 然后你打电话给这个人:

vectorimp<int> p;

因为vec是nullptr,所以程序中断。

您在
cpp
文件中定义了
multiply(矩阵,vectorimp)
,该文件是一个独立的编译单元,因此在该文件之外看不到。模板在使用/需要时被实例化,但是如果它在不同的编译单元中使用,编译器没有函数体,因此它是未定义的。 您必须将函数体放在标题中,以便函数体可用于所有需要它的编译单元(
cpp
文件)

template <class T>
void multiply (matrix<T> p, vectorimp<T> v);

template <typename T>
class matrix
  {
public:
    friend void multiply<>(matrix<T> p, vectorimp<T> v);
  };

template <class T>
void multiply (matrix<T> p, vectorimp<T> v)
{
    // whatever
}
您正在为未知类型分配
int
s
T

T **temp = new int*[rows];
这应该是:

T **temp = new T*[rows];
您将索引与模板类型混合使用:

T rows ;
T cols ;
这些与参数类型无关

如果进行这些更改,它将在没有内存泄漏的情况下工作:


manuel@desktop:~/projects$ g++ -Wall main.cc -o main -std=c++17 && valgrind --leak-check=full ./main
==16701== Memcheck, a memory error detector
==16701== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==16701== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==16701== Command: ./main
==16701== 
I am here 36
I am here 47
I am here 18
==16701== 
==16701== HEAP SUMMARY:
==16701==     in use at exit: 0 bytes in 0 blocks
==16701==   total heap usage: 13 allocs, 13 frees, 73,932 bytes allocated
==16701== 
==16701== All heap blocks were freed -- no leaks are possible
==16701== 
==16701== For counts of detected and suppressed errors, rerun with: -v
==16701== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

声明和循环中也有大量硬编码数组索引(值
3
),如果
matrix
和/或
vector
main

@drescherjm中出现大小更改,这些索引和循环将中断。请参阅免责声明,我已检查了这些链接。非常感谢再次分享。您忘记显式专门化
multiply
模板空乘(矩阵p,向量v)!=void multiply(矩阵p,向量v)
@Dani谢谢你的评论,请你详细说明一下,我没听清楚它的评论。这就是为什么您应该将所有模板代码放在头文件中。这里没有
nullptr
问题<如果
vec
中的
data
元素多于保留空间,则code>vec[i]=data[i][j]将导致问题,但是
populate1D
验证
数据的大小(
data.size()
data[i].size()
),因此在这种情况下不会出现空PTR问题。不过,还有很多其他问题,因为这是一个非常幼稚的设计。但是它被声明为
int-vec[3]
,它不是
nullptr
,只是一个3
int
的数组。哦,我没有看到,尽管这种解决问题的方法对我来说是新的,我以前从未见过有人用向量初始化静态数组的元素???
template <class T>
void multiply (matrix<T> p, vectorimp<T> v);

template <typename T>
class matrix
  {
public:
    friend void multiply<>(matrix<T> p, vectorimp<T> v);
  };

template <class T>
void multiply (matrix<T> p, vectorimp<T> v)
{
    // whatever
}
    for (int i=0; i < this->cols; i++)
    {
        delete [] this->mat[i];
    }
    delete [] this->mat;
T **temp = new int*[rows];
T **temp = new T*[rows];
T rows ;
T cols ;

manuel@desktop:~/projects$ g++ -Wall main.cc -o main -std=c++17 && valgrind --leak-check=full ./main
==16701== Memcheck, a memory error detector
==16701== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==16701== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==16701== Command: ./main
==16701== 
I am here 36
I am here 47
I am here 18
==16701== 
==16701== HEAP SUMMARY:
==16701==     in use at exit: 0 bytes in 0 blocks
==16701==   total heap usage: 13 allocs, 13 frees, 73,932 bytes allocated
==16701== 
==16701== All heap blocks were freed -- no leaks are possible
==16701== 
==16701== For counts of detected and suppressed errors, rerun with: -v
==16701== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)