c++ - 强制具有相同属性的 vector 元素的优雅方式

标签 c++ vector

标题有点模糊,但我想不出更好的措辞,这是交易:

class A
{
public:
  A();
  A( const PropertyB& b );
  PropertyA GetPropertyA();
  PropertyB GetPropertyB();
  SetPropertyA( const PropertyA& b );
  SetPropertyB( const PropertyB& b );
  //assignment not allowed
};

假设我想使用一个 std::vector< A >,但是,只有当它的所有元素对 PropertyB 具有相同的值时,拥有一个 A 的 vector 才有意义。当前的解决方案是提供一个类似于构造器的方法来创建这样的数组,它保证返回数组的所有元素对 PropertyB 具有相同的值,以及一个检查是否是这种情况的方法:

Array MakeArray( size_t, const PropertyB& );
bool CheckIfArrayIsSane( const Array& );

所以用户仍然可以在元素上调用 SetPropertyB(),但是有一个实用程序来检查它并在有人这样做时退出:

Array x( MakeArray( 3, someValue ) );
x.SetPropertyA( aaa );             //should be allowed
x.SetPropertyB( someOtherValue );  //should NOT be allowed
//somewhat further in the program
if( !CheckIfArrayIsSane( x ) )
  throw InsaneArrayExcpetion();

虽然这行得通,但它很容易出错,因为很难在所有地方强制执行此检查并且不会忘记它,并且检查会使代码困惑。

有效的方法:

  • 将 SetPropertyB() 设为私有(private),并将 MakeArray 设为友元函数:这样一来,对于只想使用 A 而不关心数组的用户而言,SetPropertyB() 将无法再访问。
  • 将 std::vector< A > 包装在一个单独的类中并且只返回 const A& 引用:这意味着其他 setter 如 SetPropertyA() 也不能被调用,但用户应该能够调用它们。只有 SetPropertyB() 应该被禁止。

一种更具侵入性的方法可行但感觉有点不雅,并且需要额外的函数在两者之间进行转换等:

class AWithFixedPropertyB
{
public:
  A( const PropertyB& b );
  PropertyA GetPropertyA();
  PropertyB GetPropertyB();
  SetPropertyA( const PropertyA& b );
};

class A : public AWithFixedPropertyB
{
public:
  //contrcutors etc
  SetPropertyB( const PropertyB& b );
};

//ok, users cannot modify property B in this Array
typedef std::vector< AWithFixedPropertyB > Array;

这个问题最优雅的解决方案是什么?

最佳答案

从 OO 设计的角度来看,这没有意义。还记得 Liskov 比喻原则吗:只要 A 对象可以用来代替 B 对象,A is-a B?根据该规则,您提议的元素 std::vector<A> is-an-A 测试失败,因为您无法设置它们的 B 属性。然而std::vector<A>应该是 A 对象的容器。

在 C++ 中,我们有私有(private)继承,这明确表明派生类与其父类有 is-a 关系。您可以按如下方式使用它:

class A_fixed_B : private A 
{
    A_fixed_B(A const& src) : A(src) {}
    A const& asA() const { return *this; } // Base Conversion is OK inside class.
    using A::GetPropertyA;
    using A::GetPropertyB;
    using A::SetPropertyA;
 };

您现在可以创建 std::vector<A_fixed_B>其行为可能符合您的预期。

关于c++ - 强制具有相同属性的 vector 元素的优雅方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6150761/

相关文章:

c++ - 如何打印 unsigned long long 的所有可能的唯一位掩码?

linux - 如何在 CLion 中链接库

c++ - 使用另一个类的变量

r - 计算数据框行中的唯一元素并返回出现次数最多的元素

c++ - 将大量二进制数据加载到 RAM 中

c++ - 为什么使用指令的范围会有所不同?

c++ - 在 WP8 项目中调试 C++ 运行时组件

arrays - MATLAB 排除超出 1 个标准差的数据

r - 如何将自定义 ggplot 别名存储为 .R 脚本中的 `list` 对象,并沿着所需的标签向量获取它们

c++ - 为什么我不能在从具有私有(private)构造函数的类扩展的 C++ 类中声明一个空构造函数