如果类 A 修改其构造参数,我可以使用常量参数初始化 const A 吗?

If class A modifies its construction parameters, can I initialize const A's with const parameters?

本文关键字:参数 常量 初始化 const 可以使 修改 如果 我可以      更新时间:2023-10-16

假设我有

class A final { 
    int& ir; 
public:
    A(int& x) : ir(x) { }
    void set(int y) { ir = y; } // non-const method!
    int get() const { return ir; }
};

const int i;

显然我不能有

 A a(i);

因为那会破坏恒常性。但我也不能有

 const A a(i);

尽管事实上这不会破坏恒常性。C++不支持"仅恒量"的 ctors,例如,在这种情况下,需要const int& .有没有办法const A a包装对i的引用 - 除了

A a(const_cast<int &>(i))

"Const" 表示对象在构造函数结束和析构函数开始之间是恒定的(在构造期间,您必须能够更改对象)。C++没有常量对象首选的"准备构造函数"。

您可以通过应用 boost::variant 来尝试此解决方法。这在编译时不是完全类型安全的,但至少通过引发异常在运行时检测错误。

#include <boost/variant.hpp>
#include <iostream>
class R {
  boost::variant<int&, const int&> v;
public:
  R(int&v):v(v) { }
  R(const int&v):v(v) { }
  // works with both
  int get() const { 
     return boost::apply_visitor( 
        [](int x){return x;}, v); 
  }
  // only works for non-const A. If at construction, a const
  // int was passed, throws an error at runtime
  void set(int x) {
     boost::get<int&>(v) = x;
  }
};

int main() {
  int a = 0;
  const int b = a;
  R r1(a);
  R r2(b);
  const R r3(a);
  std::cout << r1.get() << r2.get() << r3.get();
  // r3.set(1); // compile error
  r1.set(1); // works
  r2.set(1); // runtime error
}

>C++没有完全常量类的概念,如果引用int &仅用作const int &,编译器可能不会执行。所以基本上,你不能这样做。

很奇怪,但是

class A final {
    union{
    int& ir;
    const int &cir;
    };
public:
    A(int& x) : ir(x) { }
    A(const int& x) : cir(x) { }
    void set(int y) { ir = y; } // non-const method!
    int get() const { return ir; }
};
int main(int argc, char *argv[])
{
    const int cv = 8;
    int v = 6;
    A a( cv );
    std::cout << a.get() << std::endl;
    a.set( v );
    std::cout << a.get() << std::endl;
    return 0; 
}

此外,您的set和get方法在值而不是引用上起作用,因此看起来您做错了什么

这不是我编写代码的方式,但它以某种方式工作。如果从 const 变量构造模板类,则 set() 函数也会定义 const,并且不会更改状态。通过从非常量变量构造,set 函数能够更改状态。

#include <iostream>
#include <string>
#include <type_traits>
template<typename T>
class A
{
    T &_i;
public:
    A(T &i) : _i(i) {}
   template <typename D = T,
             typename = std::enable_if_t<std::is_const<D>::value
                                        >
            >
    void set(T i) const { std::cout << "Do nothing on set" << std::endl; }
   template <typename D = T,
             typename = std::enable_if_t<!std::is_const<D>::value>
            >    
    void set(T i) { std::cout << "Do something on set" << std::endl; }
};
int main()
{
    {
        std::cout << "Construct from NON const variable" << std::endl;
        int b = 5;
        A<decltype(b)> a(b);   
        a.set(3);
    }
   {
        std::cout << "Construct from const variable" << std::endl;
        int const  b = 5;
        A<decltype(b)> a(b);      
        a.set(3);
    }
}

这将打印:

Construct from NON const variable
Do something on set
Construct from const variable
Do nothing on set
class A { 
    const int& ir; //  <<-- it's a const int. 
    /* ... */
public:
    A(int& x) : ir(x) { }
};