在C++中创建通用对象的最佳方法?

DaC*_*lan 7 c++ generics struct

主要使用C#进行编程后,我发现自己在C++方面处于亏损状态.然而,我需要创建一个C++应用程序,因为它只是一个更大的C++解决方案中的一个组件.

情况

  • 我有一个包含数据组件(对象)的struct(Parent).这可能是任何类型的数据组件 - 即自定义结构.
  • 只有Parent(创建Parent incl对象)的编译器和终端接收器需要知道对象内部数据组件的类型,因为数据只与它们相关.
  • 然而,Parent结构可能会传递几个方法,对象甚至其他进程.
  • 对象的数据选项是有限的,编译器和反编译器都知道数据类型的不同选项.因此他们能够以原始形式反编译对象
  • 然而,这些类型可以扩展(即,虽然限制它不一定是固定的),并且反编译器和编译器将来会更新

问题 - 我不想使用"模板"重新创建可能遇到此数据组件的每个方法和对象...也看到将来可能更改数据类型建议每个进程遇到长对象的模板开始并不理想.

我正在寻找类似于C#Object的东西 - 并编写了以下组件

  • 这是一个很好的解决方案,还是我将来遇到问题
  • 是否可以对此进行改进?我没想过(特别是不包括Object\impl.h?
  • 有完全不同/更好的解决方案吗?

代码

  • 我的Header文件中有以下内容

    struct Object
    {
        Object();
        // Return true if value has succesfully been set
        // Return false if there is no compatibility between Value and result.
        template <typename T>
        bool GetValue(T &result);
        template<typename T>
        bool SetValue(T value);
        virtual LPVOID GetObjectAddress() = 0;
        virtual const char* GetType() = 0;
    };
    
    template<typename T>
    struct ObjectType:public Object
    {
            ObjectType(T value);
            T Value;
            LPVOID GetObjectAddress();
            const char* GetType();
    };
    
    Run Code Online (Sandbox Code Playgroud)

我还有一个CreateType函数用于在开始时创建几个现成的对象,例如在.h文件的末尾调用如下目的

    template class CreateType<int>;
Run Code Online (Sandbox Code Playgroud)

请记住,int只是例如......它实际上是不同的结构.

  • 我还有另一个头文件,它包含在这个头文件的底部,如下所示:

    #include "Implementation\Object_impl.h"
    -> looks like this
    
    template<typename T>
    ObjectType<T>::ObjectType(T value)
    {
        Value = value;
    };
    
    template <typename T>
    // Return true if value has succesfully been set
    // Return false if there is no compatibility between Value and result.
    bool Object::GetValue(T &result)
    {
        if (typeid(result).name() == GetType())
        {
            result = *(T *)GetObjectAddress();
            return true;
        }
        return false;
    };
    
    template<typename T>
    bool Object::SetValue(T value)
    {
        if (typeid(T).name() == GetType())
        {
            *(T*)GetObjectAddress() = value;
            return true;
        }
        return false;
    };
    
    template<typename T>
    const char* ObjectType<T>::GetType()
    {
        return typeid(Value).name();
    }
    template<typename T>
    EXPOBJ LPVOID ObjectType<T>::GetObjectAddress(){
        return (LPVOID)&Value;
    }
    
    Run Code Online (Sandbox Code Playgroud)

我希望我可以在cpp文件中包含大部分内容,但是后来我无法按需创建不同的对象......我还不确定其含义是什么......还要扩展类型只需要一个包括普通对象头文件.

我知道内联可能是一个选项,但也认为它不理想?

然而,目前这个编译并完美地作为"通用"选项.还可以通过继承自"Object"继承来扩展吗?

...哦,并使用我只是这样做 - 这似乎工作:

    Object * a;
    a = new ObjectType<testing>(testing());
    testing x = testing();
    x.i = 50;
    a->SetValue(x);
    testing y = testing();
    testing &z = y;
    a->GetValue(z);

    cout << z.i << " for z and y = " << y.i << endl;

    Result -> 50 for z and y = 50
Run Code Online (Sandbox Code Playgroud)

Moo*_*uck 7

通常,我们像对象类型一样远程避免任何事情.如果绝对必要(而且几乎从来没有),我们使用boost :: any.

至于你的代码:这实际上是非常好的,但这里我提到的一点:

你没有析构函数.这是一个主要的错误.

virtual ~Object() {}
//and
virtual ~ObjectType() {}
Run Code Online (Sandbox Code Playgroud)

此外,GetObjectAddress不是类型安全的.

class Object {
    //stuff
    template<class T>
    T* GetObjectAddress();
private: 
    virtual LPVOID GetRawPointer() = 0;
};    
template<class T>
inline T* Object::GetObjectAddress() 
{
    if (typeid(T).name() == GetType() || typeid(T).name()==typeid(void).name())
    {
        return static_cast<T*>(GetRawPointer());
    }
    return nullptr;
}
Run Code Online (Sandbox Code Playgroud)

此外,我会禁止复制和移动分配位,这有助于防止错误.

class Object {
    Object(const Object&) = delete;
    Object(Object&&) = delete;
    Object& operator=(const Object&) = delete;
    Object& operator=(Object&&) = delete;
    //stuff
};
Run Code Online (Sandbox Code Playgroud)

我会给派生类型一个默认的构造函数和转换构造函数

template<typename T>
struct ObjectType:public Object
{
    ObjectType() {}
    //C++11 here:
    template<class...Ts> 
    ObjectType(Ts...Vs) 
        :Value(std::forward<Ts>(Vs)...) {}
    //C++03 here:
    template<class first> 
    ObjectType(const first& f) : Value(f) {}
    template<class t0, class t1> 
    ObjectType(const t0& p0, const t1& p1) : Value(p0, p1) {}
    template<class t0, class t1, class t2> 
    ObjectType(const t0& p0, const t1& p1, const t2& p2) : Value(p0, p1, p2) {}
        //etc etc etc
Run Code Online (Sandbox Code Playgroud)

最后,使用智能指针而不是原始拥有指针.原始指针很好,只要他们不拥有他们指向的东西.

std::unique_ptr<Object> a;
a.reset( new ObjectType<testing>() );
Run Code Online (Sandbox Code Playgroud)

  • 对*拥有指针*的一点阐述 - 这些被称为智能指针,是[RAII]的关键组成部分(http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization).我建议你仔细阅读. (2认同)