C++ C++;:防止更改指针';常数函数中的s值
以这个虚拟结构为例:C++ C++;:防止更改指针';常数函数中的s值,c++,pointers,constants,C++,Pointers,Constants,以这个虚拟结构为例: struct foo { int* pI; void bar() const { int* ptrToI = pI; // I want this to require 'const int*' *ptrToI = 5; // I want this to fail } }__test__; 如何设计此结构以防止将pI点的值更改为?除非可以使成员常量int*,否则可以使用继承来隐藏成为子类的成员,并在基类中提
struct foo
{
int* pI;
void bar() const
{
int* ptrToI = pI; // I want this to require 'const int*'
*ptrToI = 5; // I want this to fail
}
}__test__;
如何设计此结构以防止将pI点的值更改为?除非可以使成员
常量int*
,否则可以使用继承来隐藏成为子类的成员,并在基类中提供一个受保护的函数,该函数生成常量int*
指针:
class base_foo
{
int* pI;
protected:
const int* get_pI(){return pI;}
};
struct foo : base_foo
{
int* ptrToI = get_pI(); // will fail due to attempted conversion to int*
/* and so on*/
还请注意,包含两个连续下划线的任何标记都是保留的,因此,在形式上,程序的行为是未定义的:重命名\uuuuuu test\uuuuu
您可以使用自定义智能指针来隐藏底层指针:
template <typename T>
struct ptr_t
{
private:
T *ptr;
public:
//Constructors and assignment operators
ptr_t(): ptr(nullptr) {}
ptr_t(T* p): ptr(p) {}
ptr_t(const ptr_t &other): ptr(other.ptr) {}
ptr_t& operator=(T* p) {this->ptr=p;return *this;}
ptr_t& operator=(const ptr_t &other) {this->ptr=other.ptr; return *this;}
//Note that the smart pointers included in the standard returns non-const pointers
//That is why you need to define a custom smart pointer, which forces the const pointer return in the const version of the operators.
const T* operator->() const {return ptr;}
T* operator->() {return ptr;}
const T& operator&() const {return *ptr;}
T& operator&() {return *ptr;}
operator const T*() const {return ptr;}
operator T*() {return ptr;}
};
struct foo2
{
ptr_t<int> pI;
void nonconst_bar()
{
int* ptrToI = pI; // Now success, since not const
*ptrToI = 5;
}
void failing_bar() const
{
//int* ptrToI = pI; // This fails
//*pI = 5; // This also fails
}
void success_bar() const
{
const int* ptrToI = pI;
//*ptrToI = 5; // This is not possible anymore
}
};
模板
结构ptr\t
{
私人:
T*ptr;
公众:
//构造函数和赋值运算符
ptr_t():ptr(nullptr){}
ptr_t(t*p):ptr(p){}
ptr_t(constptr_t&other):ptr(other.ptr){}
ptr_t&operator=(t*p){this->ptr=p;return*this;}
ptr_t&operator=(const ptr_t&other){this->ptr=other.ptr;返回*this;}
//请注意,标准中包含的智能指针返回非常量指针
//这就是为什么您需要定义一个自定义智能指针,强制常量指针在常量版本的运算符中返回。
常量T*运算符->()常量{return ptr;}
T*运算符->(){return ptr;}
常量T&运算符&()常量{return*ptr;}
T&运算符&({return*ptr;}
运算符常量T*()常量{return ptr;}
运算符T*(){return ptr;}
};
结构foo2
{
ptr_t pI;
无效非标准杆()
{
int*ptrToI=pI;//现在成功了,因为不是常量
*ptrToI=5;
}
无效失败_bar()常量
{
//int*ptrToI=pI;//此操作失败
//*pI=5;//这也会失败
}
void success_bar()常量
{
常数int*ptrToI=pI;
//*ptrToI=5;//这已经不可能了
}
};
const int*pI代码>?到底是什么问题?与您的问题无关,但不要使用带有两个前导下划线的符号(例如\uuuu test\uuu
),这些符号在所有范围内都是保留的。请注意,该解决方案被建议包含在C++标准中:如果不需要<代码> FoO ,并且不需要重置< <代码> PI/<代码>,那么,技术上,可以简单地使用C++引用而不是C++指针。否则,您可能会使用自定义智能指针,正如@lopital在回答中所建议的那样。但很有可能您正在重新发明类似于std::string
或std::vector
的东西,然后使用标准容器。我在链表类中使用它。你的解决方案非常适合我的西装!