切换到基类

时间:2016-10-11 11:21:32

标签: c++ pointers inheritance

我目前正在尝试将存储在共享指针中的派生类的类型切换到基类。 问题是Derived类继承自Base类,并且还模板如下:

基类:

#define PRINT(s) std::cout << s << std::endl

class Base {
public:
    Base() : m_a(1) {}
    virtual ~Base() = default;
    virtual void print() { PRINT("BASE"); }

    int m_a;
};

派生类依赖于枚举模板:

enum eType { e0, e1 };

template<eType et>
class Derived : public Base { };

template<>
class Derived<e0> : public Base {
public:
    Derived() { this->m_a = e0; }
    void print() { PRINT("Derived e0, m_a value: " << e0 ); }
};

template<>
class Derived<e1> : public Base {
public:
    Derived() { this->m_a = e1; }
    void print() { PRINT("Derived e1, m_a value: " << e1 ); }
};

我的目标是拥有一个指向Base类的共享指针,这样就可以从2个派生类切换如下:

int main()
{
    std::shared_ptr<Base> sp_00 = std::make_shared<Derived<e0>> ();

    std::shared_ptr<Base> sp_01 = sp_00;
    sp_01->print();

    std::shared_ptr<Base> sp_10 = std::make_shared<Derived<e1>> ();

    *sp_01 = *sp_10;

    sp_01->print();
    sp_10->print();
}

*sp_01 = *sp_10;上的唯一问题我希望指向基类的指针从派生类型Derived<e0>切换到派生类型Derived<e1>。但是,在我的示例中,我得到了行sp_01->print();和行sp_10->print();的不同结果,表明sp_01保持为Derived<e0>类型。

我想避免sp_01 = sp_10;因为它会改变指针。在上面的示例中,它会导致sp_00 != sp_01,我希望sp_00sp_01共享同一个对象。

我尝试用非模板派生类替换模板派生类,如下所示:

class Derived_e0 : public Base {
public:
    Derived() { this->m_a = e0; }
    void print() { PRINT("Derived e0, m_a value: " << e0 ); }
};
class Derived_e1 : public Base {
public:
    Derived() { this->m_a = e1; }
    void print() { PRINT("Derived e1, m_a value: " << e1 ); }
};

和以下代码给出的结果与带模板的结果相同。

int main()
{
    std::shared_ptr<Base> sp_00 = std::make_shared<Derived_e0> ();

    std::shared_ptr<Base> sp_01 = sp_00;
    sp_01->print();

    std::shared_ptr<Base> sp_10 = std::make_shared<Derived_e1> ();

    *sp_01 = *sp_10;

    sp_01->print();
    sp_10->print();
}

所以我的问题是,如何切换共享指针指向的派生对象而不更改shared_ptr本身(在程序的其他部分使用?)

谢谢,如果您需要更多信息,请告诉我

2 个答案:

答案 0 :(得分:1)

您无法在不重新分配sp_01的情况下更改Derived<e1>的运行时类型,因为您无法将Derived<e0>分配给Derived<e0>(想想如果这些内容不相同会发生什么情况 - 您已为Derived<e1>分配了足够的尺寸,而不是sp_00!)。

在我看来,你的设计(或者你试图用它做什么)在某个地方是有缺陷的。但是,如果你真的想保持一个&#34;链接&#34;在sp_01int main() { std::shared_ptr<Base> *psp_01; std::shared_ptr<Base> sp_00 = std::make_shared<Derived<e0>> (); psp_01 = &sp_00; (*psp_01)->print(); std::shared_ptr<Base> sp_10 = std::make_shared<Derived<e1>> (); psp_01 = &sp_10; (*psp_01)->print(); sp_10->print(); } 之间,您可能需要另一个&#34;级别&#34;指针:

DECLARE
    @Id     varchar(80),
    @Name   varchar(80),
    @NextId varchar(80)

BEGIN

    SET @MyCursor = CURSOR FOR
    SELECT id,name FROM dbo.My_TABLE
    WHERE name like '%joe%';

    OPEN @MyCursor 
        FETCH NEXT FROM @MyCursor 
    INTO @Id, @Name

    WHILE @@FETCH_STATUS = 0
    BEGIN
        print 'Id is :: ' + cast(@Id as varchar(80)) + ' : ' + @Name
        SELECT @NextId=id, LEAD (id,1) OVER (ORDER BY id) FROM @MyCursor;
        print 'The next record is :: ' + @NextId
        FETCH NEXT FROM @MyCursor 
        INTO @Id, @Name
    END; 

但是,在使用它之前,我会再次分析我的设计。

答案 1 :(得分:0)

你可以dynamic_cast原始指针;

之类的东西
Derived* t = dymanic_cast<Derived*>(sp_00.get())

如果无法投射,你将获得NULL,如果可以,你将获得有效指针。也就是说,这需要内置RTTI,这将使您的二进制文件更大,并且需要这样做表明您的设计不正确。