铸造给孩子 [英] Cast to a Child

查看:35
本文介绍了铸造给孩子的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我实际上想要做的是将构造的 moneypunct 转换为 this question 无需像 this answer 中那样编写复制构造函数.

What I'm actually trying to do is cast a constructed moneypunct to the punct_facet in this question without writing a copy constructor as in this answer.

但为了编写最小、完整、可验证的示例,假设我有这两个类:

But in the interests of writing a Minimal, Complete, Verifiable Example let's say that I have these two classes:

class Parent{
public:
    Parent(Complex& args);
    Parent operator=(const Parent&) = delete;
    Parent(const Parent&) = delete;
    Parent() = default;

    virtual void func();
private:
    Complex members;
};

class Child : public Parent{
public:
    virtual void func();
};

我可以使用默认构造函数构造 ParentChild,但不会设置 Complex members.所以说我得到了使用自定义构造函数构造的 Parent foo 并且我想将 foo 对象与 Childfunc 方法.我怎么做?直接 dynamic_cast<Child*>(&foo) 段错误,所以可能没有办法:http://ideone.com/JcAaxd

I can construct a Parent or Child with the default constructor but that won't setup Complex members. So say that I am given Parent foo which was constructed using the custom constructor and I want to use the foo object just with Child's func method. How do I do that? The straight up dynamic_cast<Child*>(&foo) segfaults, so there may not be a way: http://ideone.com/JcAaxd

auto bar = dynamic_cast<Child*>(&foo);

我是否必须创建一个 Child 构造函数,该构造函数采用 Parent 并在内部复制它?或者有什么方法可以让 bar 存在?

Do I have to make a Child constructor that takes a Parent and internally copies it? Or is there some way to cast bar into existence?

为了深入了解我的实际问题,示例中的 Parentmoneypunct,它是在标准中实现的,因此我无法修改它.

To give insight into my actual problem, the Parent from the example is moneypunct, which is implemented in the standard so I cannot modify it.

class punct_facet 是我的,示例中的 Child 继承了 moneypunct,如果我想保持实现独立,我不能甚至在内部使用 moneypunct 的成员变量.

class punct_facet is mine and the Child from the example, it inherits moneypunct and if I'm trying to stay implementation independent I cannot even internally use moneypunct's member variables.

这意味着我必须对 punct_facet 中的所有 moneypunct 成员变量进行数据镜像,并在 punct_facet 构造中复制构造它们.这会导致一个对象比它需要的胖两倍,并且需要我重新实现所有 moneypunct 功能.

Which means that I must data mirror all of moneypunct member variables in punct_facet and copy construct them on punct_facet construction. This results in an object that's twice as fat as it needs to be and requires me to reimplment all moneypunct functionality.

显然,这是不可取的,但我能找到的唯一方法是采用以前构造的 moneypunct 并将其视为 punct_facet 根据此问题的要求.

Clearly that's undesirable, but the only way I can find around it is to take a previously constructed moneypunct and treat it as a punct_facet as requested by this question.

推荐答案

它不会像你想象的那样工作,因为你已经将函数 func 虚拟化了.这意味着即使您要将指向 Parent 的指针转换为指向 Child 的指针,该对象的 func() 仍然是Parent::func().

It wouldn't work as you think, since you have made the function func virtual. This means that even if you were to convert the pointer to Parent to a pointer to Child, the func() of that object would still be Parent::func().

现在,理论上你可以这样做:

Now, you could theoretically do something like this:

#include <iostream>

class Parent
{
public:
        virtual void foo() { std::cout << "parent" << std::endl; }
};

class Child : public Parent
{
public:
        virtual void foo() { std::cout << "child" << std::endl; }
};

int main()
{
        Child child;
        child.foo(); // "child"
        child.Parent::foo(); // "parent"
        Parent parent;
        parent.foo(); // "parent"
        ((Child*)(&parent))->foo(); // still "parent"
        ((Child*)(&parent))->Child::foo(); // "child"
        return 0;
}

虽然我可能会因为发布这个损坏的代码而收到一些反对票,但我认为有必要展示在这种情况下发生的事情.您需要同时转换指向对象的指针,然后准确指定要调用的函数.

And while i may receive some downvotes for posting this broken code, i think that it is necessary to show what is happening in this case. You would need to convert both, the pointer to the object, and then specify exactly which function you are intending to call.

根据你在做什么,最好通过使用朋友类来完成:

Depending upon what you are doing, it may better be accomplished by using friend classes:

#include <iostream>

class ParentHelper;
class ChildHelper;
class Parent
{
    friend class ParentHelper;
    friend class ChildHelper;
private:
    int a=5;
};

class ParentHelper
{
public:
    virtual void func(Parent *p)
    {
        std::cout << "parent helper, but i see a " << p->a << std::endl;
    }
};

class ChildHelper : public ParentHelper
{
public:
    virtual void func(Parent *p)
    {
        std::cout << "child helper, but i see a also " << p->a << std::endl;
    }
};

void foo(Parent* p, ParentHelper *h)
{
    h->func(p);
}

int main()
{
    Parent p;
    ParentHelper ph;
    ChildHelper ch;

    ph.func(&p);
    ch.func(&p);

    foo(&p, &ph);
    foo(&p, &ch);

    return 0;
}

注意几点:

  1. 友谊不会继承,因此您必须将所有孩子列出您打算使用的 ParentHelper.
  2. 但是,它确实为您提供了一种按原样访问 Parent 类的所有数据成员的方法,它不会导致一些奇怪的行为.
  3. 这可能仍然不是您想要的,但从您的问题来看,我认为它可能会有所帮助.

这篇关于铸造给孩子的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆