Cat*_*kul 35 c++ constructor const
(编辑:重大改变,因为前面的例子是有缺陷的,这可能会使一些答案/评论看起来很奇怪)
这可能是一个过于设计,但由于缺少const构造函数,以下是合法的:
class Cheater
{
public:
Cheater(int avalue)
: cheaterPtr(this) //conceptually odd legality in const Cheater ctor
, value(avalue)
{}
Cheater& getCheaterPtr() const {return *cheaterPtr;}
int value;
private:
Cheater * cheaterPtr;
};
int main()
{
const Cheater cheater(7); //Initialize the value to 7
cheater.value = 4; //good, illegal
cheater.getCheaterPtr().value = 4; //oops, legal
return 0;
}
Run Code Online (Sandbox Code Playgroud)
似乎提供const构造函数在技术上就像const方法一样容易,并且类似于const重载.
注意:我不是在寻找' Image( const Data & data ) const'而是' const Image( const Data & data) const'
所以:
这是上下文的一些相关材料:
Mar*_*k B 10
正因为Image是const在你想象的构造并不意味着什么m_data指向是.您最终能够将"指向const的指针"分配给类中的"const指向非const",这样可以在没有强制转换的情况下删除const.这显然会允许您违反不变量而且不允许.
据我所知,在当前标准范围内,可以准确,完整地指定所需的任何特定的常数.
另一种看待它const的方法是,该方法不会改变对象的状态.构造函数的唯一目的是将对象的状态初始化为有效(无论如何 - 希望任何具有副作用的构造函数都应该......进行仔细评估).
编辑:在C++中,constness既适用于成员,也适用于指针和引用,适用于引用对象的可访问const.C++有意识地决定拆分这两个不同的常量.首先,我们是否同意这个展示差异的代码应该编译并打印出"非常量"?
#include <iostream>
struct Data
{
void non_const() { std::cout << "non-const" << std::endl; }
};
struct Image
{
Image( Data & data ) : m_data( data ) {}
void check() const { m_data.non_const(); }
Data & m_data;
};
int main()
{
Data data;
const Image img(data);
img.check();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
那么为了获得它可以接受const-ref并将其存储为const-ref的行为,引用的有效声明必须改为const.这将意味着它将是一个完全不同的类型,而不是const原始类型的版本(因为具有const-qualification不同成员的两种类型在C++中被视为两个单独的类型).因此,编译器必须能够做过多的幕后魔术来来回转换这些东西,记住成员的常量,或者它必须将它视为一个单独的类型然后不能用于代替普通类型.
我认为你想要实现的是一个referencee_const对象,这个概念只作为一个单独的类存在于C++中(我怀疑可以通过明智地使用模板来实现,尽管我没有尝试).
这是一个严格的理论问题(答案:C++决定拆分对象和引用的常量)还是有一个实际的实际未解决的问题,你试图解决?
它本身不是const方法
如果这个构造函数const本身不是一个方法,那么内部指针等也不会const.因此,它无法将const值设置为那些非const成员.
使其在语法上工作的唯一方法是此构造函数要求所有非mutable成员的成员初始化.实质上,使用此构造函数时,mutable将隐式声明未声明的任何成员const.这相当于使构造函数成为一个const方法; 只有初始化程序才能初始化成员.构造函数的主体无法对不可变成员执行任何操作,因为那些成员就const在那时.
你所要求的是语法上可疑的.您实际上是在试图欺骗API,将常量数据存储在为可变数据设计的对象中(这就是为什么您没有声明成员指针的原因const).如果您想要对象的不同行为,则需要声明该对象具有该特定行为.
Mark B 回顾了基本的考虑因素,但请注意,您可以在纯 C++ 中执行类似的操作。考虑:
struct Data { };
class ConstImage {
protected:
const Data *const_data;
public:
ConstImage (const Data *cd) : const_data(cd) { }
int getFoo() const { return const_data->getFoo(); }
};
class Image : public ConstImage {
protected:
Data *data() { return const_cast<Data *>(const_data); }
public:
Image(Data *d) : const_data(d) { }
void frob() { data()->frob(); }
};
Run Code Online (Sandbox Code Playgroud)
不要使用const Image *,而是使用ConstImage *,然后就可以了。您还可以简单地定义一个静态函数伪构造函数:
const Image *Image::newConstImage(const Data *d) {
return new Image(const_cast<Data*>(d));
}
Run Code Online (Sandbox Code Playgroud)
当然,这依赖于程序员来确保不存在任何const可能以某种方式改变所指向的Data状态的函数。
您还可以结合使用这些技术:
class Image {
protected:
const Data *const_data;
Data *data() { return const_cast<Data *>(const_data); }
public:
void frob() { data()->frob(); }
int getFoo() const { return const_data->getFoo(); }
Image(Data *d) : const_data(d) { }
static const Image *newConst(const Data *cd) {
return new Image(const_cast<Data *>(cd));
}
};
Run Code Online (Sandbox Code Playgroud)
这可以两全其美;由于data()是非常量成员,因此您可以静态检查指向值的突变。但是,您也有一个 const 构造函数,并且可以直接在Image *和之间进行转换const Image *(即,如果您知道它是安全的,则可以删除常量)。
您还可以进一步抽象出指针的分离:
template<typename T>
class ConstPropPointer {
private:
T *ptr;
public:
ConstPropPointer(T *ptr_) : ptr(ptr_) { }
T &operator*() { return *ptr; }
const T &operator*() const { return *ptr; }
T *operator->() { return ptr; }
const T *operator->() const { return ptr; }
};
class Image {
protected:
ConstPropPointer<Data> data;
public:
void frob() { data->frob(); }
int getFoo() const { return data->getFoo(); }
Image(Data *d) : data(d) { }
static const Image *newConst(const Data *cd) {
return new Image(const_cast<Data *>(cd));
}
};
Run Code Online (Sandbox Code Playgroud)
现在,如果this是 const,data则变为 const,并将其传播到其中*data。对你来说足够好了吗?:)
我想最终的答案可能是这样的:为了使 const 构造函数有用且安全,我们需要像ConstPropPointer您在语言中看到的那样的东西。const T *然后,Const 构造函数将被允许从to赋值constprop T *。这比听起来更复杂 - 例如,它如何与诸如 ? 之类的模板类交互vector?
所以,这是一个有点复杂的改变,但问题似乎并没有那么严重。更重要的是,这里有一个简单的解决方法(ConstPropPointer可以库化,并且静态伪构造函数很容易添加)。因此,C++ 委员会可能会因为更重要的事情而忽略它,即使它确实被提议过。