C++ 常量正确性/缺少支持常量和非常量实例的类的常量构造函数

C++ const correctness / missing const constructor for class supporting both const and non-const instances

本文关键字:常量 实例 非常 构造函数 支持 正确性 C++      更新时间:2023-10-16

我有几个链接类,如以下示例所示,我希望它们同时支持非常量和常量实例(如函数x(:

#include <vector>
class Original;
class View
{
public:
View(Original *that) : m(that) {}
Original * m;
};
class Original
{
public:
auto columns() {return View(this);}
//~ const auto columns() const {return View(this);} // comment #1
std::vector<int> m;
};
void x()
{
Original o1;
const Original o2;
//~ o2.columns(); // comment #2
}

我用g++ -std=gnu++17 -c const.cpp编译它并得到以下结果:

情况1:如上所述:编译得很好(这已经让我感到困惑,因为在下面的情况 2 中,我只是添加一个调用,它会失败......

案例 2:取消注释 #2,我们得到...

const.cpp: In function 'void x()':
const.cpp:24:13: error: passing 'const Original' as 'this' argument discards qualifiers [-fpermissive]
o2.columns(); // comment #2
^
const.cpp:15:7: note:   in call to 'auto Original::columns()'
auto columns() {return View(this);}
^~~~~~~

情况 3:此外,取消注释 #1; 这会产生...

const.cpp: In member function 'const auto Original::columns() const':
const.cpp:16:46: error: invalid conversion from 'const Original*' to 'Original*' [-fpermissive]
const auto columns() const {return View(this);} // comment #1
^
const.cpp:8:2: note:   initializing argument 1 of 'View::View(Original*)'
View(Original *that) : m(that) {}
^~~~

对我来说,看起来我需要一个构造函数来创建一个 const 对象,这在C++中不可用。 所以我尝试将View制作为模板类,以支持常量和非常量成员m。但我没有马上让它运行,反正感觉很丑。

有人有任何提示吗?已经非常感谢了!

您的View构造函数采用Original指针,但您正在尝试向它传递指向const Original的指针!您需要构造函数(和成员变量(来反映这一点:

class View
{
public:
View(const Original *that) : m(that) {}
const Original * m;
};

在这里看到它运行:https://ideone.com/nEgFxD

但是,如果您愿意接受制作深度复制的打击,那么更好的做法是完全避免指针业务:

//Declare Original out so View can use its copy/move constructor
class Original
{
public:
auto columns();
const auto columns() const;
std::vector<int> m;
};
//Full declaration/implementation of View
class View
{
public:
View(const Original &that) : m(that) { }
Original m;
};
//Now that View's constructors are defined, implement these Original funcs
auto Original::columns() {return View(*this);}
const auto Original::columns() const {return View(*this);} // comment #1
int main()
{
Original o1;
const Original o2;
o2.columns(); // comment #2
}

在这里看到它运行:https://ideone.com/HnpQ38

这是我今天想出的,但基于模板(我认为相当丑陋(; 它同时支持常量和非常量用法(如函数x

(:
#include <vector>
class Original;
template<class T>
class View
{
public:
View(T *that) : m(that) {}
T * m;
};
class Original
{
public:
auto columns() {return View(this);}
const auto columns() const {return View(this);}
std::vector<int> m;
};
void x()
{
Original o1;
const Original o2;
o2.columns();
}