C++ 如果不使用dynamic_cast<;,我如何知道具体的对象类型&燃气轮机;()

C++ 如果不使用dynamic_cast<;,我如何知道具体的对象类型&燃气轮机;(),c++,c++14,C++,C++14,我使用的是复合设计模式,我想从我的复合类中克隆我的对象。我试图在我的组件类中创建一个泛型克隆方法,但是当我试图将对象的具体类型发送给泛型(模板)方法时,“typeof”和“typeid”返回抽象类类型。所以,当我尝试使用newtypeof(object)时,我看到了错误 抽象类类型“Component”的新表达式无效 我的编译器是32位的 因为我不知道对象的类型,所以我不能使用dynamic_cast 我是否错误地使用了typeof/typeid,还是应该使用其他关键字来了解具体的对象类型 #i

我使用的是复合设计模式,我想从我的复合类中克隆我的对象。我试图在我的组件类中创建一个泛型克隆方法,但是当我试图将对象的具体类型发送给泛型(模板)方法时,“typeof”和“typeid”返回抽象类类型。所以,当我尝试使用newtypeof(object)时,我看到了错误

抽象类类型“Component”的新表达式无效

我的编译器是32位的

因为我不知道对象的类型,所以我不能使用dynamic_cast

我是否错误地使用了typeof/typeid,还是应该使用其他关键字来了解具体的对象类型

#include <iostream>
#include <vector>
#include <typeinfo>

class Component
{
public:
    template <typename Tdest> typename std::remove_cv<typename std::remove_pointer<Tdest>::type>::type* clone() const
    {
        typedef typename std::remove_cv<typename std::remove_pointer<Tdest>::type>::type NO_POINTER_NOR_CV;
        return new typeof(NO_POINTER_NOR_CV)(*dynamic_cast<const NO_POINTER_NOR_CV*>(this));
    }

    virtual void manipulateComponents() = 0;
    virtual void add(Component* comp) = 0;

protected:
    std::vector<const Component*> _v;
};

class Leaf : public Component
{
    void manipulateComponents() override { return; }
    void add(Component* comp) override { return; }
};

class Composite : public Component
{
public:
    void manipulateComponents() override
    {
        for(auto component : _v)
        {
            std::cout << typeid(component).name() << std::endl; // print PK9Component
            component->clone<typeof(component)>();

            /* ... */
        }
    }

    void add(Component* comp) override { _v.push_back(comp); }
};

int main(int argc, char* argv[])
{
    Component* l = new Leaf();
    Component* c = new Composite();
    Component* parent = new Composite();
    parent->add(l);
    parent->add(c);

    parent->manipulateComponents();
}
#包括
#包括
#包括
类组件
{
公众:
模板typename std::remove_cv::type*clone()const
{
typedef typename std::remove_cv::type NO_POINTER_或_cv;
返回新的typeof(无指针或CV)(*dynamic_cast(this));
}
虚空操纵器组件()=0;
虚空添加(组件*comp)=0;
受保护的:
std::vector_v;
};
类叶:公共组件
{
void manipleComponents()重写{return;}
无效添加(组件*comp)重写{return;}
};
类组合:公共组件
{
公众:
void manipleComponents()重写
{
对于(自动组件:_v)
{
标准::不能添加(l);
父->添加(c);
父->操纵组件();
}

您没有使用
typeid
获取派生类型的详细信息,因为您正在指针上使用它。请在调用中取消引用pionter以获取派生类型的名称

改变

std::cout << typeid(component).name() << std::endl; // print PK9Component
// PK9Component seems indicate that it is a pointer to a Component.

std::cout克隆方法中的
typeof
magic不会为您提供非模板类的子类类型。它可以为您提供实例化模板的类型,但此处克隆方法的唯一可能实例化是在基类中。子类化不会重新定义模板方法

如果你真的想,如果你愿意使用“奇怪的重复模板模式”,你可以在子类化中使用模板方法

// Base class has a pure virtual function for cloning
class Shape {
public:
    virtual ~Shape() {};
    virtual Shape *clone() const = 0;
};
// This CRTP class implements clone() for Derived
template <typename Derived>
class Shape_CRTP : public Shape {
public:
    virtual Shape *clone() const {
        return new Derived(static_cast<Derived const&>(*this));
    }
};

// Nice macro which ensures correct CRTP usage
#define Derive_Shape_CRTP(Type) class Type: public Shape_CRTP<Type>

// Every derived class inherits from Shape_CRTP instead of Shape
Derive_Shape_CRTP(Square) {};
Derive_Shape_CRTP(Circle) {};
//基类具有用于克隆的纯虚拟函数
阶级形态{
公众:
虚拟~Shape(){};
虚拟形状*克隆()常量=0;
};
//此CRTP类为派生类实现clone()
模板
类形状\u CRTP:公共形状{
公众:
虚拟形状*克隆()常量{
返回新的派生(静态_cast(*this));
}
};
//尼斯宏,确保正确的CRTP使用
#定义派生形状CRTP(类型)类类型:公共形状CRTP
//每个派生类都从Shape_CRTP而不是Shape继承
导出{u形}CRTP(正方形){};
导出_形_-CRTP(圆){};

如果需要克隆方法,则必须添加一个虚拟函数以返回该方法,如下所示:

struct A
{
    virtual std::unique_ptr<A> clone() const = 0;

    A() = default;
    A(A const&) = default;
    A(A&&) = default;
    A& operator=(A&&) = default;
    A& operator=(A const&) = default;

    virtual ~A() = default;
};

struct B : A
{
    std::unique_ptr<A> clone() const override
    {
        assert(typeid(*this) == typeid(B));
        return std::make_unique<B>(*this);
    }
};
结构A { 虚拟std::unique\u ptr,但暂时不可用。

使用CRTP,您可以执行以下操作:

template <typename Derived>
class IClonable
{
public:
    virtual ~IClonable() = default;
    std::unique_ptr<Derived> clone() const {
        return std::unique_ptr<Derived>(cloneImpl());
    }
protected:
    virtual Derived* cloneImpl() const = 0;
};

template <typename Derived, typename Base>
class Clonable : public Base
{
public:
    std::unique_ptr<Derived> clone() const { // Hide Base::clone to return static type.
        return std::unique_ptr<Derived>(static_cast<Derived*>(cloneImpl()));
    }
protected:
    Clonable* cloneImpl() const { return new Derived{static_cast<const Derived&>(*this)}; }
};
模板
类可克隆
{
公众:
virtual~IClonable()=默认值;
std::unique_ptr clone()常量{
返回std::unique_ptr(cloneImpl());
}
受保护的:
虚拟派生*cloneImpl()常量=0;
};
模板
类Clonable:公共基
{
公众:
std::unique_ptr clone()const{//Hide Base::clone返回静态类型。
返回std::unique_ptr(静态_cast(cloneImpl());
}
受保护的:
Clonable*cloneImpl()常量{返回新的派生{static_cast(*this)};}
};
然后:

class Component : public IClonable<Component>
{
public:
    virtual void manipulateComponents() = 0;
    virtual void add(const Component&) = 0;
};

class Leaf : public Clonable<Leaf, Component>
{
public:
    void manipulateComponents() override {}
    void add(const Component&) override {}
};

class Composite : public Clonable<Composite, Component>
{
public:
    void manipulateComponents() override
    {
        for (const auto* component : _v)
        {
            auto cloned = component->clone(); // std::unique_ptr<Component>

            /* ... */
        }
    }

    void add(const Component& comp) override { _v.push_back(&comp); }
protected:
    std::vector<const Component*> _v;
};
类组件:公共IClonable
{
公众:
虚空操纵器组件()=0;
虚拟空添加(常量组件&)=0;
};
类叶:公共可克隆
{
公众:
void manufacteComponents()重写{}
无效添加(常量组件&)重写{}
};
类复合:公共可克隆
{
公众:
void manipleComponents()重写
{
对于(常数自动*组件:_v)
{
自动克隆=组件->克隆();//std::unique_ptr
/* ... */
}
}
void add(const Component&comp)重写{{u v.push_back(&comp)}
受保护的:
std::vector_v;
};
可能的用法:

Leaf l;
Composite c;
auto parent = c.clone(); // std::unique_ptr<Composite>
parent->add(l);
parent->add(c);

parent->manipulateComponents();
l叶;
复合c;
auto parent=c.clone();//std::unique_ptr
父项->添加(l);
父->添加(c);
父->操纵组件();

您的错误消息来自
new Composite();
无效(因为
Composite
是抽象的)-请修复这些编译错误,以便提供一个适当的示例,显示您的
typeid
组件的问题不存在(也不应该存在)知道如何克隆子类的实例。只需让<代码>克隆> <代码>纯虚拟,让每个子类都做它自己的克隆。为什么不能使用<代码> DyjixSCAST ?这里可能不重要,但我假设所有的GCC衍生物都有非常相似的前端(即消化类似的C++方言和构造)。。区别在于后端,即它们生成的代码以及它们链接的库。考虑到这一点,版本号可能比Mingw、cygwin gcc或linux box上的版本号更重要。它可以打印预期的类型。但我可以将其作为模板参数发送吗?不,不能将其用作模板参数r、 这两者都是因为typeid不生成类型,而动态类型只在运行时知道,而不是编译时知道。
Leaf l;
Composite c;
auto parent = c.clone(); // std::unique_ptr<Composite>
parent->add(l);
parent->add(c);

parent->manipulateComponents();