Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/150.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;:防止更改指针';常数函数中的s值_C++_Pointers_Constants - Fatal编程技术网

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
的东西,然后使用标准容器。我在链表类中使用它。你的解决方案非常适合我的西装!