【问题标题】:Is there a way to forbid casting to subclass that is non-const in C++?有没有办法禁止转换为 C++ 中非常量的子类?
【发布时间】:2009-05-08 07:48:25
【问题描述】:

这是一个完整的例子。 我想通过只允许转换来禁止使用从 B 转换到 A 的对象的 A::set B 到常量 A。 怎么做? (我不能使用虚函数)

#include <iostream>
#include <cassert>

using namespace std;

class A {
public:
  int  get() const { return i_; }
  void set(int i) { i_ = i; }
protected:
  int i_;
};

class B : public A {
public:
  int  ok() const { return A::get() == copy_i_; }
  void set(int i) { A::set(i); copy_i_ = i; }
protected:
  int copy_i_;
};

void test2() {
  A a;
  a.set(3); // ok here
  cout << a.get() << endl;

  B b;
  b.set(5);
  A& aa = b;
  assert(b.ok());
  aa.set(3); // not ok here
  assert(b.ok()); // fail-here
}

int main() {
  test2();
  return 0;
}

【问题讨论】:

    标签: c++ inheritance constants


    【解决方案1】:

    您可以将继承设为私有,并在 B 中提供一个成员函数来使用而不是强制转换。

    const A& B::convert_to_A() const { return *this; }
    

    【讨论】:

    • 正是我需要的,谢谢。
    【解决方案2】:

    为什么要选角?将 void A::set(int i) protected 设为适用于您的情况。

    【讨论】:

    • 但是我想修改纯A对象。
    【解决方案3】:

    没有必要禁止非常量强制转换。您可以使用template method design pattern 解决您的问题。

    #include "stdafx.h"
    #include <iostream>
    #include <cassert>
    
    using namespace std;
    
    class A {
    public:
      int  get() const { return i_; }
      void set(int i) { assert(i_ = i); copy_i();}
    
    protected:
      int i_;
      virtual void copy_i(){};
    };
    
    
    class B : public A {
    public:
      int  ok() const { return A::get() == copy_i_; }
    protected:
      int copy_i_;
      void copy_i(){copy_i_ = i_; }
    };
    
    void test2() {
      B b;
      b.set(5);
      A& a = b;
      assert(b.ok());
      a.set(3);
      assert(b.ok()); // success!
    }
    
    int main() {
      test2();
      return 0;
    }
    

    【讨论】:

    • 正如我所说,由于性能原因,我不能使用虚函数。如果 A 类可以保持不变,那就太好了。
    • 在这种情况下我不认为它可以做到。但是,您是否真的分析过您的应用程序以确保虚拟功能太慢?虚函数的开销通常可以忽略不计。
    • 我做了个人资料。虚函数太慢了,因为它们不能被内联
    • A::set() 中的 assert() 可能不会做你想做的事。它将在带有参数 0 的调用中被击中。
    猜你喜欢
    • 2010-11-17
    • 2018-10-23
    • 1970-01-01
    • 2020-09-29
    • 2018-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多