是否可以同时声明const / non-const的类成员?

时间:2018-10-29 02:44:20

标签: c++ class const

我有一个可以将非常量指针或常量指针作为其重载构造函数的参数的类。在我的特定情况下,我需要同时从类const的{​​{1}}和non-const方法中实例化该类的对象,但是由于无法分配指向T的const指针。

foo

是否可以将两个构造函数中的参数都分配给myClass() { public: myClass(T* v); myClass(const T* v); // ... T* foo; // ... } ?如果是这样,正确的语法是什么?

编辑:

在更具体的情况下,我有一个类foo,它包装在myClass周围,并允许我通过嵌套类std::vector直接访问向量的子集:

mySubset

其中的代码无关-基本上 template<typename _type> myClass() { std::vector<_type> data; public: class mySubset(){ myClass<type>* foo; public: mySubset(myClass<_type>* _in) { foo = _in; }; mySubset(const myClass<_type>* _in) { foo = _in; /* error */ }; // ... } // ... myClass(); // ... void mySubset method() { return mySubset(this); };; void mySubset const_method const() { return mySubset(this); /* error */ }; // ... } 允许读取和写入特定的向量位置。虽然我可以通过单独的const和非const嵌套类实现所需的功能,但我正在寻找一种使用单个返回类型实现此目的的方法。

3 个答案:

答案 0 :(得分:2)

我认为您将不得不重新考虑您的设计,因为您无法使用T*左值来初始化const T*,而如果没有const_cast,则应该避免使用const当然,(因为如果您在放弃常量后修改常量指针,它将调用未定义的行为)

相反,您可以为non consttemplate <typename T> class myClass { public: //myClass(T* v):foo(v) { } myClass( T* v):foo(v) { } // ... T* foo; // ... }; 使用模板类型推导

int a =42;
const int* p1 = &a;
int *p2 = &a;

myClass  X1(p1); //C++17 auto type deduction or use myClass<const int> X1(p1)
myClass  X2(p2);

然后

Redraw

答案 1 :(得分:0)

您可以在const_cast构造函数中使用const T*,但通常不应该这样做。

const T*的意思是“指向常数T”,而您存储“指向T的指针”。如果执行const强制转换,最终可能会修改一个不应修改的值。如果您不打算修改foo,只需声明const T*并使用单个const T*构造函数即可。

我会检查这是否是设计问题。这些情况经常出现: (1)当您将指针存储为非常量时,它应该是常量。通常,这是因为您正在访问另一个对象中的值,并且应该在每个使用站点将对象作为(可能是const)引用传递,而不是存储指向该对象的指针。 (2)当您确实要存储对象的副本时,在这种情况下,您只需保留一个常规T并将其作为const T&传递给构造函数。 (3)您正在处理原始的C样式字符串,并希望将内容复制到自己的缓冲区中。

答案 2 :(得分:0)

如果您不想使用参数化类型(模板)类作为@ P0W的答案,则不可能只使用一个指针来接受所有常量和非常量指针类型。您需要另一个常量指针类型,以便在包装器类中仅接受const <your another class> *。 在包装类中有两种您可能不喜欢的指针类型之后,下面的代码起作用。

#include <iostream>

using namespace std;

class SomeObject {
public:
    SomeObject(){}
    explicit SomeObject(int i):testVal(i){}
private:
    int testVal;
};

class PtWrapper {
public:
    PtWrapper(SomeObject *pso);
    PtWrapper(const SomeObject *cpso);
private:
    SomeObject *pSO;
    const SomeObject *cpSO;
};



int main(int argc, char *argv[]) {
    SomeObject so(133);
    SomeObject *pso = &so;
    const SomeObject cso(166);
    const SomeObject *cpso = &cso;
    PtWrapper pw1(pso);
    PtWrapper pw2(cpso);
    return 0;
}

PtWrapper::PtWrapper(SomeObject *pso) :pSO(pso){

}

PtWrapper::PtWrapper(const SomeObject *cpso):cpSO(cpso){}