【问题标题】:Cast const member function to non-const将 const 成员函数强制转换为非常量
【发布时间】:2015-07-29 10:59:59
【问题描述】:

是否正在转换 C++ 中定义的成员函数指针的constness?以下代码是否有效?

struct T {
  void foo(int i) const { std::cout << i << std::endl;};
};

void (T::*f1)(int) const = &T::foo;
void (T::*f2)(int)       = reinterpret_cast<void (T::*)(int)>(f1);
T t;
(t.*f2)(1);

更新:

我需要这个的原因是我正在编写一个函数,它同时接受一个对象和一个指向该对象的成员函数指针。我需要一个用于 const 对象的版本(只接受 const 函数)和一个普通的版本。因为我不想重复代码,所以我的想法是将实际代码放在非常量版本中,然后从 const 版本中调用它,丢弃任何 const。

【问题讨论】:

  • 即使定义了你也不应该这样做。 const 变量是 const 是有原因的
  • @Gir 好吧,没那么容易。放弃对变量的 const-ness 基本上是为了增加可写性(即提高期望值),而放弃对这个方法的 const-ness 试图让函数不必给出“I不会改变内部状态”保证(即降低期望)。
  • @Gir 但这些不是变量。您似乎没有理解 const 关键字在应用于函数时的含义。
  • 但它不会改变函数的行为,你需要这个做什么??
  • @klm123:它不会改变任何东西。 const 是 c++ 程序的语法糖,除非您像“static const int i = 1;”一样使用它。这可能会被优化,除非你在某处写“&i”,否则不会。对于函数来说更是如此。您不能将任何内容传递给将被优化的函数,因此您可以公然抛弃并返回函数内部或外部的任何 const。

标签: c++ casting constants


【解决方案1】:

编译器吃掉它。 但是向后转换更有用。

再一次但是 - 最好不要使用它, const_cast 通常只是一个快速而肮脏的解决方案,只有在没有任何其他解决方案时才应用它。

回答更新

如果我理解正确,您将使用一个对象和两个函数。第一个函数接受 const 对象和 const 成员函数,第二个 - 非常量对象和非常量成员函数。

根据给定的信息,您可以将第二个函数更改为接受非常量对象和 const 成员函数。并给他们一个非常量对象及其 const 成员函数。

【讨论】:

    【解决方案2】:

    是的,它是定义的,但如果函数真的是 const,你可能不想要它,因为一些编译器优化(即返回值缓存)依赖于函数是 const。

    【讨论】:

      【解决方案3】:

      可以,但是没有意义,哪里可以调用f2,也可以调用f1。你应该以另一种方式投射。但如果有的话,你应该转换对象,而不是函数。

      void (T::*f1)(int) const = &T::foo;
      void (T::*f2)(int)       = reinterpret_cast<void (T::*)(int)>(f1);
      T t;
      (t.*f2)(1); // compiles
      (t.*f1)(1); // this compiles too!!
      

      如果你有

      const T t;
      (t.*f2)(1); // error t is const
      (t.*f1)(1); // still compiles
      

      【讨论】:

        【解决方案4】:

        解决歧义的唯一方法是执行 static_cast,这基本上是一种语言特性

        #include <boost/typeof/typeof.hpp>
        struct Test
        {
            const int& foo();
            const int& foo() const;
        };
        
        int main()
        {
            typedef const int&(Test::*non_const_ptr)();
            typedef const int&(Test::*const_ptr)()const;
            BOOST_TYPEOF(static_cast<non_const_ptr>(&Test::foo)) ss;
        }
        

        【讨论】:

          【解决方案5】:

          我看不出这样做的理由:即使可以,也要限制更多。 假设你有一个 Foo 类:

          class Foo {
            void f() const;
            void g();
          }
          

          还有一些sn-p代码:

          Foo a;
          const Foo b;
          

          然后您可以同时调用a.f()a.g(),但不能调用b.g(),因为bconst。如您所见,将const 放在成员函数之后可以减少限制,而不是增加限制。

          并且,通过reinterpret_cast这个指针,你将得到具有完全相同值的指针(由于reinterpret_cast的性质),如果你尝试调用它,你会进入相同的T ::foo()

          【讨论】:

            猜你喜欢
            • 2019-05-04
            • 1970-01-01
            • 2019-07-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多