如果A类修改了它的构造参数,我可以用const参数初始化const A吗?

时间:2016-04-21 14:57:54

标签: c++ constructor const const-correctness const-cast

假设我有

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 ++不支持“const-only”ctors,例如在这种情况下,将采用const int&。有没有办法让const A a包含对i的引用 - 除了

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

5 个答案:

答案 0 :(得分:4)

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

您可以通过应用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
}

答案 1 :(得分:3)

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

答案 2 :(得分:1)

很奇怪但是

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方法在值上操作而不是引用,所以它看起来像你做错了什么

答案 3 :(得分:1)

这不是我如何编写代码但它以某种方式工作。 如果从const变量构造模板类,则set()函数也定义为const,并且不会更改状态。通过从非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

答案 4 :(得分:0)

class A { 
    const int& ir; //  <<-- it's a const int. 
    /* ... */
public:
    A(int& x) : ir(x) { }
};