C++ 中复制构造函数的问题使用模板
距离我上次用 C/C++ 写东西已经有十多年了,现在我遇到了一个无法解决的问题。基本上我有两个类,比如 CA 和 CB,其中 CA 看起来像一个向量,CB 看起来像一个二维矩阵。
我面临的问题是我想构造一个 CB 类型的对象,并通过使用另一个 CB 类型的对象来实现。因此,我将一个已正确初始化的 CB 类型的对象作为参数传递,但当我这样做时,我收到以下形式的错误: ./Bh:97:43: error: no vivailable重载运算符[]对于类型“const CB
。
我复制对象的方式是依赖类CA的复制机制。话虽如此,通过使用 CA 类的另一个初始化对象来构造 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
,那么程序编译没有问题,输出也很好。
我尝试创建一个最小的示例,这是我可以缩小代码的范围。
关于如何使用复制使构造函数工作有什么想法吗?我很感激你的时间。
以下是文件
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;
}
Ah:
#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);
}
Bh:
#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();
}
It has been more than a decade since the last time I wrote something in C/C++ and now I have a problem I cannot solve. Basically I have two classes, say CA and CB, where CA looks like a vector and CB looks like a two-dimensional matrix.
The issue that I am facing is that I want to construct an object of type CB and do so by using another object of type CB. Therefore, I pass as a parameter an object of type CB that has been initialized correctly, but when I do that, I get an error of the form ./B.h:97:43: error: no viable overloaded operator[] for type 'const CB<double>'
.
The way I copy the object is by relying on the copying mechanism for class CA. Having said that, constructing an object of class CA by using another initialized object of class CA appears to be working fine. So, I am a little bit lost as to what is wrong. I also get additional help from the compiler for my error, but I am not sure how to fix things really. The full error that I receive using g++ is the following:
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.
There must be something that I do not remember how to do, or most likely, I am not aware of. Note that if you comment the offending line fromm main.cpp (line 24) with the command CB<double> myPrecious(mycb_c);
, then the program compiles without a problem and the output is fine.
I tried to create a minimal example and this is as far as I could shrink the code.
Any ideas on how to make the constructor work by using copy? I appreciate your time.
BELOW ARE THE FILES
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();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题是当前您已将
operator[]
重载为类模板CB
的非常量成员函数 。这意味着该成员函数的隐式this
参数的类型为CB*
。这意味着我们只能将这个成员函数用于非常量对象。要解决这个问题,您需要将其(重载为)const 成员函数,而不是添加一个
const
,如下所示,这样现在隐式this
参数将是const CB*
类型,这意味着现在它可以与const 对象。
程序在修改后编译,如此处所示。
The problem is that currently you have overloaded
operator[]
as a non-const member function of class templateCB
. This means that the implicitthis
parameter of this member function is of typeCB<DataType>*
. Meaning that we can use this member function only with non-const objects.To solve this problem you need to make it(overload it as) a const member function instead by adding a
const
as shown below, so that now the implicitthis
parameter will be of typeconst CB<DataType>*
meaning now it can be used withconst
objects.The program compiles after the modification as can be seen here.