继承和指针

Inheritance and pointers

本文关键字:指针 继承      更新时间:2023-10-16

我有这样的代码:

class Human
{
    protected:
        int age;
        std::string sex;    
    public: 
        virtual void speak() = 0;
};
class Child:public Human
{
    public:
        void speak(){std::cout << "I am Childn";}
};
class Man:public Human
{
    public: 
        void speak(){std::cout << "I am Mann";}
};
class Woman:public Human
{
    public: 
        void speak(){std::cout << "I am Womann";}
};
(don't know, std::shared_ptr<Human> maybe?) operator*(std::shared_ptr<Child> &b, int x)
{
    b->setAge(b->getAge()+x);
    if(b->getAge()>18 && b->getSex()=="Man")
    {
        return (i want b to become std::shared_ptr<Man>)
    }
    if(b->getAge()>18 && b->getSex()=="Woman")
    {
        return (here I want b to become std::shared_ptr<Woman>);
    }
    return;
}
int main(){
    auto x = std::make_shared<Child>;
    x*19;
}

我知道这似乎很奇怪,但这是我能想到的最简单的情况,而不必写下我在RN中挣扎的所有代码。有人可以解释什么类型应该是哪种类型,以及如何更改共享_ptr类型,知道他们是从同一父母派生的?

对象无法更改类型。Child对象始终是Child对象。您可以做的是使用所需的属性创建一个新的对象,然后返回:

std::shared_ptr<Human> operator*(std::shared_ptr<Human> b, int x)
{
    b->setAge(b->getAge()+x);
    if(b->getAge()>18 && b->getSex()=="Man") {
        return std::make_shared<Man>(b->getAge());
    } else if(b->getAge()>18 && b->getSex()=="Woman") {
        return std::make_shared<Woman>(b->getAge());
    } else {
       return b;
    }
}
int main(){
    std::shared_ptr<Human> x = std::make_shared<Child>;
    x = x*19;
}

这似乎不是一个好设计。Human的儿童或成人状态将更好地表示为对象的属性,或者通过检查age是否大于18的函数。

您无法使T<Derived>类型从T<Base>继承,因为C 模板不支持协方差。这样做对于某些类型来说将是不安全的,例如对容器的可变引用。(想象一下将std::vector<Cat>提及为std::vector<Animal>&并推回狗!)

(我会给这个答案作为评论,但我没有评论能力。)

更新:您可以编写处理堆数据的非模板包装器:

class Wrapper
{
public:
  Wrapper(Base* b) : raw(b) {}
  ~Wrapper() { delete raw; }
  Base& get() { return *base; }
private:
  Base* raw;
}

当然,在您的示例中,您使用std :: shared_ptr,而不是std :: unique_ptr。您必须处理参考计数,而不是简单地删除毁灭仪中的数据,但是保持内部原始指针的技术仍然存在。

更新2:

可以使用上述代码提供一定的间接水平,以便所有从基类继承的类都可以以相同类型保存,而无需编写自己的参考计数器:

std::shared_ptr<Wrapper>

此解决方案可能被视为类似于执行std::shared_ptr<Base*>,除了后一个解决方案会泄漏内存。