代码之家  ›  专栏  ›  技术社区  ›  changelog

C++中如何使用C类属性

  •  11
  • changelog  · 技术社区  · 15 年前

    我正在考虑C++在个人项目中的应用。我想让它独立于平台(不需要MNO,因为一些平台还不支持它),这就是为什么我考虑C++。

    然而,我有一个疑问。我已经很喜欢C的属性了,我想知道我是否可以用C++中的类似东西。

    另外,是否可以使用装饰器模式进行此操作?

    编辑:我现在考虑其他可能的或近似的事情,例如,在运行时附加一个类到一个类的方法。

    9 回复  |  直到 15 年前
        1
  •  9
  •   Alex Martelli    15 年前

    要在大多数OO语言中“在运行时将其他行为附加到类”,我建议 Strategy 设计模式——让类(和/或它的实例)保持(通过C++中的指针,其他语言中的[可重新引用]引用)一个合适的接口/抽象类的实例,称为“策略接口”(用一种方法[Virtual C++ in ]当然是非最终语言。 final 等等——瞧,一个 压倒

    最后,类或实例必须通过它所持有的策略接口实例的方法来委托所有适当的功能。

    在适当的情况下,您可以通过各种方式修改基本策略DP方法;例如,当可修改功能整齐地分成几个内聚组时,最好将策略对象“分割”为几个简单内聚组(DrawingStrategy、PersistenceStrategy、BusinessRulessStrategy等)。

    整个方法不能代替执行适当的分析,因此也不能代替适当的设计,因为它不允许沿着最初未考虑的轴扩展类功能;相反,该方法旨在作为一种适当的解决方法 经过深思熟虑的设计,以良好控制的方式为可扩展性提供“挂钩”。如果新的考虑因素开始发挥作用,那么仍然有必要迭代和完善类的设计,以涵盖这些新思想。但是,迭代开发(包括对原始设计的调整和扩展)在任何丰富、复杂的现实世界项目中都是不可避免的——策略DP只是箭袋中的一支箭,有助于使过程更加有序和有效。

        2
  •  6
  •   Daniel Earwicker    15 年前

    对于类属性,是。只需定义一个名为Attributes的基类来存储属性信息,并在任何需要属性的类中继承它。您可以使用RTTI cast查询它。

    但对于方法或参数属性,这基本上不是一个选项。

        3
  •  3
  •   Christopher Karper    15 年前

    自己构建一个预处理器,将类似属性的语法转换为实际的属性和方法。

        4
  •  3
  •   Paolo Tedesco    15 年前

    关于如何使用模板专门化“模拟”类属性的想法:

    #include <string>
    #include <iostream>
    
    // attribute classes: the default implementation returns some
    // default values for the attributes properties
    template<typename TheClass> 
    struct Attribute1{
        static const int Value = 0;
    };
    
    template<typename TheClass> 
    struct Attribute2{
        static const std::string Value(){
            return "";
        }
    };
    

    // define a type without attributes
    struct ClassWithoutAttributes{
    };
    

    如果要将属性应用于类,则使用模板专门化:

    // define a type with attributes; we "simulate" the attributes     
    // template specialization
    struct ClassWithAttributes{
    };
    
    // template-specialize Attribute1 for the class we want to apply the
    // attribute to...
    template<>
    struct Attribute1<ClassWithAttributes>{
        static const int Value = 1;
    };
    
    // template-specialize Attribute2 
    template<>
    struct Attribute2<ClassWithAttributes>{
        static const std::string Value(){
            return "SomeString";
        }
    };
    

    我们必须应用(模板专用化)我们希望应用到的每个类的属性:

    class Item{
    };
    
    template<>
    struct Attribute1<Item>{
        static const int Value = 2;
    };
    

    例子:

    // how to use the fake attributes:
    void main(){
        // no template specialization for "ClassWithoutAttributes" => the compiler picks up the "default" values
        std::cout << "Attribute1 for type 'ClassWithoutAttributes' : " << Attribute1<ClassWithoutAttributes>::Value << std::endl;
        std::cout << "Attribute2 for type 'ClassWithoutAttributes' : " << Attribute2<ClassWithoutAttributes>::Value() << std::endl;
        // here the compiler picks up the attribute classes specialized for "ClassWithAttributes"
        std::cout << "Attribute1 for type 'ClassWithAttributes' : " << Attribute1<ClassWithAttributes>::Value << std::endl;
        std::cout << "Attribute2 for type 'ClassWithAttributes' : " << Attribute2<ClassWithAttributes>::Value() << std::endl;
    }
    

    通过这种方式,属性被“应用”到类,而不是像多重继承那样应用到实例;无论如何,根本的区别在于,在这种情况下,属性是在编译时计算的,而不是在运行时。

    :修改示例以显示如何将多个属性应用于一个类以及如何将同一属性应用于多个类。

        5
  •  1
  •   deft_code    15 年前

    C++0x将支持有限的属性。但我怀疑这会对你当前的项目,甚至对你接下来的几个项目有帮助(它暂时不会在这里)。

    你可以有点支持属性。这一点的一般实现将更加复杂。但对于一次性而言,这可能很容易

    class Foo
    {
        class MyI_property
        {
        public:
            MyI_property( Foo* parent ) :
                m_parent(parent)
            { }
    
            // getter
            operator int( void )
            { return m_parent->get_i(); }
    
            // setter
            MyI_property& operator = ( int i )
            { m_parent->set_i(i); }
    
            // some other operators you might want to implement
            int* operator&( void );
            MyI_property& operator += ( int rhs );
    
        private:
            Foo* m_parent;
        };
    
    public:
        Foo( void ) :
            MyI(this)
        { }
    
        MyI_property MyI;
    
    private:
        int& get_i( void );
        void set_i( int i );
    };
    
    Foo f;
    
    f.MyI = 10; // calls Foo::set_i
    int i = f.MyI; // calls Foo::get_i
    int j = 2 * f.MyI + f.MyI;
    
    // could work with proper overloads in MyI_property
    f.MyI += 20;
    int& i = f.MyI;
    int* i = &f.MyI;
    

        6
  •  1
  •   EricSchaefer    15 年前

    属性描述元数据。您可以通过从一个基类继承来“手动”实现,该基类为类部件(如方法)定义了一个“描述”存储库。不过,您需要在编译时提供部件的名称。

    class whatever
    {
    public:
        static map<string, string> attribute_repository;
    }
    

    这种痛苦可能不值得付出代价。。。

        7
  •  1
  •   Rob Fonseca-Ensor    15 年前
        8
  •  1
  •   yoco    15 年前

    我读了一篇关于这个问题的文章 CodeProject 关于这个问题: C++ implementation of the C# Property and Indexer with Accessor-Modifiers . 我相信这就是你想要的。

        9
  •  0
  •   Sergii Volchkov    15 年前

    在您提到的MVC示例中,通过反射使用方法属性。由于C++没有反射,所以可以考虑使用代码生成:某种接口定义语言和生成C++代码的生成器。在这个场景中,您可以自由地将属性概念添加到接口语言中,并使生成器以适当的方式转换属性。

    谷歌就是一个很好的例子 protocol buffers 当前位置有一个特殊的 .proto format