使用模板的 C++ 中的复制构造函数出现问题
Trouble with a copy-constructor in C++ using templates
距离我上次在C/C++写东西已经十多年了,现在我有一个我无法解决的问题。基本上我有两个 classes,比如说 CA 和 CB,其中 CA 看起来像一个向量 而 CB 看起来像一个二维矩阵.
我面临的问题是我想构造一个 CB 类型的对象,并通过使用另一个 CB 类型的对象来实现。因此,我将一个已正确初始化的 CB 类型的对象作为参数传递,但是当我这样做时,我收到 ./B.h:97:43: error: no viable overloaded operator[] for type 'const CB<double>'
.
形式的错误
我复制对象的方式是依靠class CA的复制机制。话虽如此,通过使用 class CA 的另一个初始化对象构建 class CA 的对象似乎工作正常。所以,我对出了什么问题有点迷茫。对于我的错误,我还从编译器获得了额外的帮助,但我不确定如何真正解决问题。我使用 g++ 收到的完整错误如下:
In file included from main.cpp:1:
./B.h:97:43: error: no viable overloaded operator[] for type 'const CB<double>'
(*theRows)[i] = new CA <DataType>(m[i]);
^ ~
./B.h:105:2: note: in instantiation of member function 'CB<double>::copy' requested here
copy(a);
^
main.cpp:24:16: note: in instantiation of member function 'CB<double>::CB' requested here
CB<double> myPrecious(mycb_c);
^
./B.h:21:27: note: candidate function not viable: 'this' argument has type 'const CB<double>', but method is not marked const
virtual CA<DataType>& operator[] (int index);
^
1 error generated.
一定是有些事情我不记得怎么做了,或者很可能我不知道。请注意,如果您使用命令 CB<double> myPrecious(mycb_c);
注释违规行 fromm main.cpp(第 24 行),则程序编译没有问题并且输出正常。
我尝试创建一个最小的示例,这是我可以缩小代码的范围。
关于如何使用复制使构造函数工作有什么想法吗?感谢您的宝贵时间。
以下是文件
main.cpp:
#include "B.h"
int main()
{
CA<double> myca_a(3);
CA<double> myca_b(myca_a);
CB<double> mycb_c(2, 3, 3.0);
CB<double> mycb_d(3, 2, 4.0);
CB<double> mycb_e;
cout << "<separator>" << endl;
cout << myca_a << endl;
cout << "<separator>" << endl;
cout << myca_b << endl;
cout << "<separator>" << endl;
cout << mycb_c << endl;
cout << "<separator>" << endl;
cout << mycb_d << endl;
cout << "<separator>" << endl;
cout << mycb_e << endl;
cout << "<separator>" << endl;
CB<double> myPrecious(mycb_c);
return 0;
}
A.h:
#include <iostream>
using namespace std;
template <class DataType>
class CA
{
protected:
DataType* paDataType;
int _size;
void copy(const CA<DataType>& ac);
public:
CA();
CA(int n);
CA(int n, const DataType& o);
CA(const CA<DataType>& ac);
virtual ~CA();
int size() const;
DataType& operator [] (int k);
void operator= (const CA<DataType>& ac);
friend ostream& operator<<(ostream& os, CA<DataType>& a) {
os << "[";
for (int i = 0; i < a.size() - 1; i++)
os << a[i] << " ";
os << a[a.size() - 1] << "]";
return os;
}
};
//Empty constructor
template <class DataType>
CA<DataType>::CA()
{
paDataType = new DataType[1];
_size = 1;
}
//Constructor
template <class DataType>
CA<DataType>::CA(int n)
{
paDataType = new DataType[n];
_size = n;
}
//Constructor w/ value
template <class DataType>
CA<DataType>::CA(int n, const DataType& o)
{
paDataType = new DataType[n];
_size = n;
for (int i = 0; i < _size; i++) paDataType[i] = o;
}
//Copy Constructor
template <class DataType>
CA<DataType>::CA(const CA<DataType>& ac)
{
copy(ac);
}
//Copy method
template <class DataType>
void CA<DataType>::copy(const CA<DataType>& ac)
{
paDataType = new DataType[ac._size];
_size = ac._size;
for (int i = 0; i < _size; i++)
paDataType[i] = ac.paDataType[i];
}
//Destructor
template<class DataType>
CA<DataType>::~CA()
{
if (paDataType != NULL)
delete[] paDataType;
paDataType = NULL;
_size = 0;
}
//Size method
template <class DataType>
int CA<DataType>::size() const
{
return _size;
}
//Accessor
template <class DataType>
DataType& CA<DataType>::operator [] (int k)
{
return paDataType[k];
}
//Overloaded assignment operator
template <class DataType>
void CA<DataType>::operator= (const CA<DataType>& ac)
{
if (paDataType != NULL) delete[] paDataType;
copy(ac);
}
B.h:
#include "A.h"
template <class DataType>
class CB : public CA <CA <DataType> >
{
protected:
CA < CA<DataType>* >* theRows;
void copy(const CB<DataType>& m);
void deleteRows();
public:
CB();
CB(int n, int m);
CB(int n, int m, DataType v);
CB(const CB& a);
virtual ~CB();
void operator= (const CB<DataType>& a);
virtual int size() const;
int columns();
int rows();
virtual CA<DataType>& operator[] (int index);
friend ostream& operator<<(ostream& os, CB<DataType>& m) {
int rows = m.rows();
int cols = m.columns();
os << "----------" << endl;
for (int i = 0; i < rows-1; i++) {
for (int j = 0; j < cols-1; j++) {
os << m[i][j] << " ";
}
os << m[i][cols-1] << endl;
}
for (int j = 0; j < cols-1; j++) {
os << m[rows-1][j] << " ";
}
os << m[rows-1][cols-1] << endl;
os << "----------";
return os;
}
};
template <class DataType> CB<DataType>::CB() {
theRows = new CA <CA <DataType>* >(1, NULL);
(*theRows)[0] = new CA <DataType>();
}
template <class DataType>
CB<DataType>::CB(int n, int m)
{
theRows = new CA <CA <DataType>* >(n, NULL);
for (int i = 0; i < n; i++)
{
(*theRows)[i] = NULL;
(*theRows)[i] = new CA <DataType>(m);
}
}
template <class DataType>
CB<DataType>::CB(int n, int m, DataType v)
{
theRows = new CA <CA <DataType>* >(n, NULL);
for (int i = 0; i < n; i++)
{
(*theRows)[i] = new CA <DataType>(m, v);
}
}
template <class DataType>
void CB<DataType>::deleteRows()
{
if (theRows != NULL)
{
for (int i = 0; i < theRows->size(); i++)
{
if ((*theRows)[i] != NULL) delete (*theRows)[i];
(*theRows)[i] = NULL;
}
delete theRows;
}
theRows = NULL;
}
template <class DataType>
CB<DataType>::~CB()
{
deleteRows();
}
template <class DataType>
void CB<DataType>::copy(const CB<DataType>& m)
{
deleteRows();
theRows = new CA <CA <DataType>* >(m.size(), NULL);
for (int i = 0; i < m.size(); i++)
{
(*theRows)[i] = new CA <DataType>(m[i]);
}
}
template <class DataType>
CB<DataType>::CB(const CB<DataType>& a)
{
deleteRows();
copy(a);
}
template <class DataType>
void CB<DataType>::operator= (const CB<DataType>& a)
{
copy(a);
}
template <class DataType>
int CB<DataType>::size() const
{
return theRows->size();
}
template <class DataType>
CA<DataType>& CB<DataType>::operator[] (int index)
{
return (*(*theRows)[index]);
}
template <class DataType>
int CB<DataType>::rows()
{
return theRows->size();
}
template <class DataType>
int CB<DataType>::columns()
{
return (*this)[0].size();
}
问题是目前你已经重载了operator[]
作为non-const成员函数 class 模板 CB
。这意味着这个成员函数的隐式this
参数是CB<DataType>*
类型。这意味着我们只能将此成员函数用于 non-const 个对象。
要解决这个问题,你需要通过添加[=15]使其成为一个常量成员函数 =] 如下所示,因此现在 隐式 this
参数将是 const CB<DataType>*
类型,这意味着现在它可以与 const
对象一起使用。
template <class DataType>
class CB : public CA <CA <DataType> >
{
virtual CA<DataType>& operator[] (int index) const; //added const here
//other members here
}
template <class DataType>
CA<DataType>& CB<DataType>::operator[] (int index) const //added const here
{
return (*(*theRows)[index]);
}
//other code here
修改后程序编译可见here.
距离我上次在C/C++写东西已经十多年了,现在我有一个我无法解决的问题。基本上我有两个 classes,比如说 CA 和 CB,其中 CA 看起来像一个向量 而 CB 看起来像一个二维矩阵.
我面临的问题是我想构造一个 CB 类型的对象,并通过使用另一个 CB 类型的对象来实现。因此,我将一个已正确初始化的 CB 类型的对象作为参数传递,但是当我这样做时,我收到 ./B.h:97:43: error: no viable overloaded operator[] for type 'const CB<double>'
.
我复制对象的方式是依靠class CA的复制机制。话虽如此,通过使用 class CA 的另一个初始化对象构建 class CA 的对象似乎工作正常。所以,我对出了什么问题有点迷茫。对于我的错误,我还从编译器获得了额外的帮助,但我不确定如何真正解决问题。我使用 g++ 收到的完整错误如下:
In file included from main.cpp:1:
./B.h:97:43: error: no viable overloaded operator[] for type 'const CB<double>'
(*theRows)[i] = new CA <DataType>(m[i]);
^ ~
./B.h:105:2: note: in instantiation of member function 'CB<double>::copy' requested here
copy(a);
^
main.cpp:24:16: note: in instantiation of member function 'CB<double>::CB' requested here
CB<double> myPrecious(mycb_c);
^
./B.h:21:27: note: candidate function not viable: 'this' argument has type 'const CB<double>', but method is not marked const
virtual CA<DataType>& operator[] (int index);
^
1 error generated.
一定是有些事情我不记得怎么做了,或者很可能我不知道。请注意,如果您使用命令 CB<double> myPrecious(mycb_c);
注释违规行 fromm main.cpp(第 24 行),则程序编译没有问题并且输出正常。
我尝试创建一个最小的示例,这是我可以缩小代码的范围。
关于如何使用复制使构造函数工作有什么想法吗?感谢您的宝贵时间。
以下是文件
main.cpp:
#include "B.h"
int main()
{
CA<double> myca_a(3);
CA<double> myca_b(myca_a);
CB<double> mycb_c(2, 3, 3.0);
CB<double> mycb_d(3, 2, 4.0);
CB<double> mycb_e;
cout << "<separator>" << endl;
cout << myca_a << endl;
cout << "<separator>" << endl;
cout << myca_b << endl;
cout << "<separator>" << endl;
cout << mycb_c << endl;
cout << "<separator>" << endl;
cout << mycb_d << endl;
cout << "<separator>" << endl;
cout << mycb_e << endl;
cout << "<separator>" << endl;
CB<double> myPrecious(mycb_c);
return 0;
}
A.h:
#include <iostream>
using namespace std;
template <class DataType>
class CA
{
protected:
DataType* paDataType;
int _size;
void copy(const CA<DataType>& ac);
public:
CA();
CA(int n);
CA(int n, const DataType& o);
CA(const CA<DataType>& ac);
virtual ~CA();
int size() const;
DataType& operator [] (int k);
void operator= (const CA<DataType>& ac);
friend ostream& operator<<(ostream& os, CA<DataType>& a) {
os << "[";
for (int i = 0; i < a.size() - 1; i++)
os << a[i] << " ";
os << a[a.size() - 1] << "]";
return os;
}
};
//Empty constructor
template <class DataType>
CA<DataType>::CA()
{
paDataType = new DataType[1];
_size = 1;
}
//Constructor
template <class DataType>
CA<DataType>::CA(int n)
{
paDataType = new DataType[n];
_size = n;
}
//Constructor w/ value
template <class DataType>
CA<DataType>::CA(int n, const DataType& o)
{
paDataType = new DataType[n];
_size = n;
for (int i = 0; i < _size; i++) paDataType[i] = o;
}
//Copy Constructor
template <class DataType>
CA<DataType>::CA(const CA<DataType>& ac)
{
copy(ac);
}
//Copy method
template <class DataType>
void CA<DataType>::copy(const CA<DataType>& ac)
{
paDataType = new DataType[ac._size];
_size = ac._size;
for (int i = 0; i < _size; i++)
paDataType[i] = ac.paDataType[i];
}
//Destructor
template<class DataType>
CA<DataType>::~CA()
{
if (paDataType != NULL)
delete[] paDataType;
paDataType = NULL;
_size = 0;
}
//Size method
template <class DataType>
int CA<DataType>::size() const
{
return _size;
}
//Accessor
template <class DataType>
DataType& CA<DataType>::operator [] (int k)
{
return paDataType[k];
}
//Overloaded assignment operator
template <class DataType>
void CA<DataType>::operator= (const CA<DataType>& ac)
{
if (paDataType != NULL) delete[] paDataType;
copy(ac);
}
B.h:
#include "A.h"
template <class DataType>
class CB : public CA <CA <DataType> >
{
protected:
CA < CA<DataType>* >* theRows;
void copy(const CB<DataType>& m);
void deleteRows();
public:
CB();
CB(int n, int m);
CB(int n, int m, DataType v);
CB(const CB& a);
virtual ~CB();
void operator= (const CB<DataType>& a);
virtual int size() const;
int columns();
int rows();
virtual CA<DataType>& operator[] (int index);
friend ostream& operator<<(ostream& os, CB<DataType>& m) {
int rows = m.rows();
int cols = m.columns();
os << "----------" << endl;
for (int i = 0; i < rows-1; i++) {
for (int j = 0; j < cols-1; j++) {
os << m[i][j] << " ";
}
os << m[i][cols-1] << endl;
}
for (int j = 0; j < cols-1; j++) {
os << m[rows-1][j] << " ";
}
os << m[rows-1][cols-1] << endl;
os << "----------";
return os;
}
};
template <class DataType> CB<DataType>::CB() {
theRows = new CA <CA <DataType>* >(1, NULL);
(*theRows)[0] = new CA <DataType>();
}
template <class DataType>
CB<DataType>::CB(int n, int m)
{
theRows = new CA <CA <DataType>* >(n, NULL);
for (int i = 0; i < n; i++)
{
(*theRows)[i] = NULL;
(*theRows)[i] = new CA <DataType>(m);
}
}
template <class DataType>
CB<DataType>::CB(int n, int m, DataType v)
{
theRows = new CA <CA <DataType>* >(n, NULL);
for (int i = 0; i < n; i++)
{
(*theRows)[i] = new CA <DataType>(m, v);
}
}
template <class DataType>
void CB<DataType>::deleteRows()
{
if (theRows != NULL)
{
for (int i = 0; i < theRows->size(); i++)
{
if ((*theRows)[i] != NULL) delete (*theRows)[i];
(*theRows)[i] = NULL;
}
delete theRows;
}
theRows = NULL;
}
template <class DataType>
CB<DataType>::~CB()
{
deleteRows();
}
template <class DataType>
void CB<DataType>::copy(const CB<DataType>& m)
{
deleteRows();
theRows = new CA <CA <DataType>* >(m.size(), NULL);
for (int i = 0; i < m.size(); i++)
{
(*theRows)[i] = new CA <DataType>(m[i]);
}
}
template <class DataType>
CB<DataType>::CB(const CB<DataType>& a)
{
deleteRows();
copy(a);
}
template <class DataType>
void CB<DataType>::operator= (const CB<DataType>& a)
{
copy(a);
}
template <class DataType>
int CB<DataType>::size() const
{
return theRows->size();
}
template <class DataType>
CA<DataType>& CB<DataType>::operator[] (int index)
{
return (*(*theRows)[index]);
}
template <class DataType>
int CB<DataType>::rows()
{
return theRows->size();
}
template <class DataType>
int CB<DataType>::columns()
{
return (*this)[0].size();
}
问题是目前你已经重载了operator[]
作为non-const成员函数 class 模板 CB
。这意味着这个成员函数的隐式this
参数是CB<DataType>*
类型。这意味着我们只能将此成员函数用于 non-const 个对象。
要解决这个问题,你需要通过添加[=15]使其成为一个常量成员函数 =] 如下所示,因此现在 隐式 this
参数将是 const CB<DataType>*
类型,这意味着现在它可以与 const
对象一起使用。
template <class DataType>
class CB : public CA <CA <DataType> >
{
virtual CA<DataType>& operator[] (int index) const; //added const here
//other members here
}
template <class DataType>
CA<DataType>& CB<DataType>::operator[] (int index) const //added const here
{
return (*(*theRows)[index]);
}
//other code here
修改后程序编译可见here.